Problems with functions - "expected primary expression" error

I'm trying to learn how to create functions within a sketch so that it makes my program a bit neater for when I have to read raw data from the sensor. It's failing with the error "Sketch1:56: error: expected primary-expression before 'int'" which I assume is due to gyroraw(int x, int y, int z); what have I done wrongly?

#include <Wire.h>

#define DEVICE (0x68)    //device address
#define TO_READ (6)        //num of bytes we are going to read each time (two bytes for each axis)

byte buff[TO_READ] ;    //6 bytes buffer for saving data read from the device
char str[512];                      //string buffer to transform data before sending it to the serial port
int offset[3];

//Function Definitions

void gyroraw(int x, int y, int z)
{
  int regAddress = 0x1D;    //first register
  readFrom(DEVICE, regAddress, TO_READ, buff);
  x= (buff[0] << 8) | buff[1];   
  y= (buff[2] << 8) | buff[3];
  z= (buff[4] << 8) | buff[5];
}

void writeTo(int device, byte address, byte val) 
  {
  Wire.beginTransmission(device); //start transmission to device 
  Wire.write(address);        // send register address
  Wire.write(val);        // send value to write
  Wire.endTransmission(); //end transmission
  } // end of writeTo
 
void readFrom(int device, byte address, int num, byte buff[]) 
  {
  Wire.beginTransmission(device); //start transmission to device 
  Wire.write(address);        //sends address to read from
  Wire.endTransmission(); //end transmission
  
  Wire.requestFrom(device, num);    // request 6 bytes from device
  
  int i = 0;
  while(Wire.available())    //device may send less than requested (abnormal)
    { 
    buff[i] = Wire.read(); // receive a byte
    i++;
    }
  }  // end of readFrom

//Begin program

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  delay(100);
  //Turning on
  writeTo(DEVICE, 0x3E, 128);
  writeTo(DEVICE, 0x16, 24);

}  // end of setup

void loop()
{
  int x, y, z;
  gyroraw(int x, int y, int z);
  //we send the x y z values as a string to the serial port
  sprintf(str, "%d %d %d", x, y, z);  
  Serial.write(str);
  Serial.write(byte(10));
  
  //It appears that delay is needed in order not to clog the port
  delay(250);
}  // end of loop

You don't declare the parameter types when you call a function, only when you define it, so it should be:

  gyroraw(x, y, z);

Thank you :slight_smile: That compiles for me now, although it doesn't seem to be actually returning anything, am I correct in saying it's because void gyroraw doesn't return anything and x,y,z are only local variables?

void gyroraw(int x, int y, int z)
{
  int regAddress = 0x1D;    //first register
  readFrom(DEVICE, regAddress, TO_READ, buff);
  x= (buff[0] << 8) | buff[1];   
  y= (buff[2] << 8) | buff[3];
  z= (buff[4] << 8) | buff[5];
}

How would I fix this in my code?

How would I fix this in my code?

make them references:

void gyroraw(int& x, int& y, int& z)

but you'll need to put in an explicit prototype for the function - the IDE isn't good with references.

You could just make x, y and z global.

AWOL:

How would I fix this in my code?

make them references:

void gyroraw(int& x, int& y, int& z)

but you'll need to put in an explicit prototype for the function - the IDE isn't good with references.

I've seen that int& x before in code, what does the & indicate? How would I go about making x y and z global variables? If i do this at the top it still yields nothing:

#include <Wire.h>

#define DEVICE (0x68)    //device address
#define TO_READ (6)        //num of bytes we are going to read each time (two bytes for each axis)

byte buff[TO_READ] ;    //6 bytes buffer for saving data read from the device
char str[512];                      //string buffer to transform data before sending it to the serial port
int offset[3];
int x, y, z;

You need to remove all other definitions of x,y and z, and not pass them as parameters.

#include <Wire.h>

#define DEVICE (0x68)    //device address
#define TO_READ (6)        //num of bytes we are going to read each time (two bytes for each axis)

byte buff[TO_READ] ;    //6 bytes buffer for saving data read from the device
char str[512];                      //string buffer to transform data before sending it to the serial port
int offset[3];
int x, y, z;


//Function Definitions

void gyroraw()
{
  int regAddress = 0x1D;    //first register
  readFrom(DEVICE, regAddress, TO_READ, buff);
  x= (buff[0] << 8) | buff[1];   
  y= (buff[2] << 8) | buff[3];
  z= (buff[4] << 8) | buff[5];
}

void writeTo(int device, byte address, byte val) 
{
  Wire.beginTransmission(device); //start transmission to device 
  Wire.write(address);        // send register address
  Wire.write(val);        // send value to write
  Wire.endTransmission(); //end transmission
} // end of writeTo

void readFrom(int device, byte address, int num, byte buff[]) 
{
  Wire.beginTransmission(device); //start transmission to device 
  Wire.write(address);        //sends address to read from
  Wire.endTransmission(); //end transmission

    Wire.requestFrom(device, num);    // request 6 bytes from device

  int i = 0;
  while(Wire.available())    //device may send less than requested (abnormal)
  { 
    buff[i] = Wire.read(); // receive a byte
    i++;
  }
}  // end of readFrom

//Begin program

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  delay(100);
  //Turning on
  writeTo(DEVICE, 0x3E, 128);
  writeTo(DEVICE, 0x16, 24);

}  // end of setup

void loop()
{
  gyroraw();
  //we send the x y z values as a string to the serial port
  sprintf(str, "%d %d %d", x, y, z);  
  Serial.write(str);
  Serial.write(byte(10));

  //It appears that delay is needed in order not to clog the port
  delay(250);
}  // end of loop

I've seen that int& x before in code, what does the & indicate

It means the variable is passed by reference, so if you make a change to the parameter within the function, that value is reflected in the actual variable you passed.

Normally, in C, parameters are passed by value, which means a local copy of the variable is taken when the function is called, and all operations are performed on that copy, so the actual parameter is isolated from changes.

The other way of doing what you want is to pass in a pointer to the variable to the function, and deference the pointer within the function.

Yes, you code snippet made the variables global, but we can't see the rest of the code.

I'd guess that you still have x, y and z as parameters in your function. If you're going the global route you will need to remove them from the function definition and call. Better to use references though as AWOL suggested.

AWOL:

How would I fix this in my code?

make them references:

void gyroraw(int& x, int& y, int& z)

but you'll need to put in an explicit prototype for the function - the IDE isn't good with references.

No you don't. However as I discovered when I was doing this test, you have buff as a global anyway. Better make up your mind if you want the function to be independent or not.

This compiles:

char buff [10];

void gyroraw(int & x, int & y, int & z)
{
  int regAddress = 0x1D;    //first register
  x= (buff[0] << 8) | buff[1];   
  y= (buff[2] << 8) | buff[3];
  z= (buff[4] << 8) | buff[5];
}

void setup ()
{
  int a, b, c;
  gyroraw (a, b, c);
}
void loop () {}

Thank you AWOL that makes sense. The original code works with the change you suggested.

I've tried the global variable route with this code:

#include <Wire.h>

#define DEVICE (0x68)    //device address
#define TO_READ (6)        //num of bytes we are going to read each time (two bytes for each axis)

byte buff[TO_READ] ;    //6 bytes buffer for saving data read from the device
char str[512];                      //string buffer to transform data before sending it to the serial port
int offset[3];
int x, y, z;
//Function Definitions

void gyroraw(int x, int y, int z)
{
  int regAddress = 0x1D;    //first register
  readFrom(DEVICE, regAddress, TO_READ, buff);
  x= (buff[0] << 8) | buff[1];   
  y= (buff[2] << 8) | buff[3];
  z= (buff[4] << 8) | buff[5];
}

void writeTo(int device, byte address, byte val) 
  {
  Wire.beginTransmission(device); //start transmission to device 
  Wire.write(address);        // send register address
  Wire.write(val);        // send value to write
  Wire.endTransmission(); //end transmission
  } // end of writeTo
 
void readFrom(int device, byte address, int num, byte buff[]) 
  {
  Wire.beginTransmission(device); //start transmission to device 
  Wire.write(address);        //sends address to read from
  Wire.endTransmission(); //end transmission
  
  Wire.requestFrom(device, num);    // request 6 bytes from device
  
  int i = 0;
  while(Wire.available())    //device may send less than requested (abnormal)
    { 
    buff[i] = Wire.read(); // receive a byte
    i++;
    }
  }  // end of readFrom

//Begin program

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  delay(100);
  //Turning on
  writeTo(DEVICE, 0x3E, 128);
  writeTo(DEVICE, 0x16, 24);

}  // end of setup

void loop()
{
  gyroraw(x, y, z);
  //we send the x y z values as a string to the serial port
  sprintf(str, "%d %d %d", x, y, z);  
  Serial.write(str);
  Serial.write(byte(10));
  
  //It appears that delay is needed in order not to clog the port
  delay(250);
}  // end of loop

But it doesn't return any values for x y and z.

Is there any advantage using global variables rather than &?

void gyroraw(int x, int y, int z)

If you use globals, you cannot pass them as parameters with the same name.void gyroraw(void)

Thanks AWOL, I see now. Is that why byte buff[TO_READ] can be passed even though it's global because it's referenced as byte buff[]? :slight_smile:

Also thanks Nick, I've managed to get both my sensors communicating now and learning alot in the process!