Scope problem

Hi,

I have a problem with my class functions.

The order of them is this:

class name
{
protected:
//variables;
//void write function(arguments){//sends data to I2C connection//variable data1;}
//void read function(arguments){//receives data over I2C in forms of bytes in variables. the bytes variables were declared in the protected identifier, outside the function.//variable data2;}
public:
//void switcher function(){//condition statement. 1st condition: print1(). 2st condition:print2().}
//int print1 function(){//assign values from read function to int variables, then it return the values}
//int print2 function()//assign values from read function to int variables, then it return the values}
private:
};

The functions marked in red indicate were the error appears.
The error that is giving me is:
-In function print1(function read wasn't declared in this scope, variable data1 wasn't declared in this scope)
-In function print2(function read wasn't declared in this scope, variable data2 wasn't declared in this scope)

Thank you,
RobertEagle

Can't see any code

Try posting the actual code that the compiler is given rather than just the parts. If the problem was that obvious, you would ahve already found it.

The .cpp file

#include <ITG3200.h>
#include <Wire.h>

void itg3200::write(byte address, byte val)
{
	Wire.beginTransmission(ITG3200);
	Wire.write(address);
	Wire.write(val);
	Wire.endTransmission();
}

void itg3200::read(byte address, int num)
{
	Wire.beginTransmission(ITG3200);
	Wire.write(address);
	Wire.endTransmission();
	if(num==2)
	{
		Wire.beginTransmission(ITG3200);
		Wire.requestFrom(ITG3200,num);
		byte i=0;
		while(Wire.available())
		{
			temp[i]=Wire.read();
			i++;
		}
		Wire.endTransmission();
	}
	else if(num==6)
	{
		Wire.beginTransmission(ITG3200);
		Wire.requestFrom(ITG3200,num);
		byte i=0;
		while(Wire.available())
		{
			gyro[i]=Wire.read();
			i++;
		}
		Wire.endTransmission();
	}
}

bool itg3200::intr()
{
	bool ready=1;
	//have to verify on Arduino validity, interrupt activity, data pending
	return ready;
}

void itg3200::init()
{
	/* default values*/
	sampleRate_default=0b00000000;
	fullScale_default=0b00011000;
	interrupt_default=0b00000000;
	power_default=0b00000000;

	/*initialization procedures*/
	write(SMPLRT_DIV,sampleRate_default);
	write(DLPF_FS,fullScale_default);
	write(INT_CFG,interrupt_default);
	write(PWR_MGM,power_default);//8000Hz sample rate
}

void itg3200::switcher()
{
	if(intr()>0)
	{
		int counter=0;
		if(counter>=8000)
		{
			counter=0;
			getTemp();
		}
		else
		{
			getGyro();
		}
		counter++;
	}
}

int getGyro()
{
	int output[2];
	read(GYRO_OUT,6);
	output[0]=(((int)gyro[0]) << 8) | gyro[1];
	output[1]=(((int)gyro[2]) << 8) | gyro[3];
	output[2]=(((int)gyro[4]) << 8) | gyro[5];
	return output[2];
}

int getTemp()
{
	int grade;
	read(TEMP_OUT,2);
	grade=(((int)temp[0]) << 8) | temp[1];
	return grade;
}

the .h file:

#ifndef ITG3200_h
#define ITG3200_h
#include <Arduino.h>

/*Register Map - In comparation with Adxl345, this whole register function*/
#define ITG3200 0x68//Device address
#define SMPLRT_DIV 0x15//SampleRate Divisor
#define DLPF_FS 0x16//Digital low pass filter, full scale
#define INT_CFG 0x17//Interrupt configuration
#define INT_STATUS 0x1A//Interruput status
#define TEMP_OUT 0x1B//Temperature out, 0x1B->0x1C
#define GYRO_OUT 0x1D//Gyroscope out, 0x1D->0x22
#define PWR_MGM 0x3E//Power management

class itg3200
{
protected:
	byte sampleRate_default;
	byte fullScale_default;
	byte interrupt_default;
	byte power_default;
	byte temp[1];
	byte gyro[5];
	void write(byte address, byte val);
	void read(byte address, int num);
	bool intr();
public:
	void init();
	void switcher();
	int getGyro();
	int getTemp();
private:
};

#endif

and the error:D:\Programs\arduino-1.0.1\libraries\ITG3200\ITG3200.cpp: In function 'int getGyro()':
D:\Programs\arduino-1.0.1\libraries\ITG3200\ITG3200.cpp:87: error: 'read' was not declared in this scope
D:\Programs\arduino-1.0.1\libraries\ITG3200\ITG3200.cpp:88: error: 'gyro' was not declared in this scope
D:\Programs\arduino-1.0.1\libraries\ITG3200\ITG3200.cpp: In function 'int getTemp()':
D:\Programs\arduino-1.0.1\libraries\ITG3200\ITG3200.cpp:97: error: 'read' was not declared in this scope
D:\Programs\arduino-1.0.1\libraries\ITG3200\ITG3200.cpp:98: error: 'temp' was not declared in this scope

In the cpp file, this:
int getGyro()
should be:
int itg3200::getGyro()

and this:
int getTemp()
should be:
int itg3200::getTemp()

Otherwise they are not declared as class members, and thus cannot find class functions such as read() and class variables such as temp[].

It's amusing..it was under my nose.
Thank you.

No, it isn't amusing, and it illustrates why we ask people to post their code, and not some digest of what they think is the problem.

Yes. You're right. And it proves that people are just subjective..

Hi again,

I don't want to start a new topic in Sensors because it's a quick question. After I've made the change in the code all seemed to work fine. After 1 hour of leaving it off, I started again to look at the measurements. This time the Z axis and the temperature data was the same.
What could have happened? I don't find any mistake in the code above.

I don't know if this is causing that problem but in the switcher() function:

		 int counter=0;
		 if(counter>=8000)
		 {
			 counter=0;
			 getTemp();
		 }
		 else
		 {
			 getGyro();
		 }
		 counter++;

counter is a local variable which will never be be >= 8000, so getTemp will never be called.

Also, in getGyro()

int itg3200::getGyro()
{
	 int output[2];
	 read(GYRO_OUT,6);
	 output[0]=(((int)gyro[0]) << 8) | gyro[1];
	 output[1]=(((int)gyro[2]) << 8) | gyro[3];
	 output[2]=(((int)gyro[4]) << 8) | gyro[5];
	 return output[2];
}

output is an array of 2 ints, so how can you assign something to output[2]? (Out of bounds array access anyone...)
Also, you are returning output[2] , which ignoring the fact it is not part of the array doesn't return output[0] and output[1], so what is the point in calculating them?

Thirdly, again with switcher()

void itg3200::switcher()
{
	 if(intr()>0)
	 {

What is the point in that if statement as intr() is defined as:

bool itg3200::intr()
{
	 bool ready=1;
	 //have to verify on Arduino validity, interrupt activity, data pending
	 return ready;
}

so that if statement essentially boils down to:

void itg3200::switcher()
{
	 if(1>0)
	 {

Firstly,
the thing with the intr function is for tomorrow. I didn't have time to finish it. So I left a free space. For the moment it's being bypassed.

Secondly the counter must be made a static.

And thirdly, can you explain me how should I do return the 3 data from the gyro? honestly, at least in my perception, I've always done it this way (the array) and it always worked. Maybe I'm too tired, or for god damn I forgot C++.

Thank you

PS: I think I got it: using pointers. (for the output data)

This is one way to do it (granted it doesn't check if the array is the correct size)

void itg3200::getGyro(int* output){
	 read(GYRO_OUT,6);
	 output[0]=(((int)gyro[0]) << 8) | gyro[1];
	 output[1]=(((int)gyro[2]) << 8) | gyro[3];
	 output[2]=(((int)gyro[4]) << 8) | gyro[5];
}

Which would then by used like this:

int output[3] = {0}; //doesn't have to be called output, call it whatever you want
getGyro(output); //pass a reference to the local array

Then you can just access the array normally. e.g. something = output[0];

Note that there are 3 (THREE) bytes in the array declaration as you need array[0], array[1] and array[2].

An alternative is to make the output[3] array a private variable of your class, that way it can be accessed anywhere within the class without having to pass the function a pointer.

In header:

class itg3200
{
private:
	int output[3];
protected:
	 ...

In cpp:

void itg3200::getGyro(){
	 read(GYRO_OUT,6);
	 output[0]=(((int)gyro[0]) << 8) | gyro[1];
	 output[1]=(((int)gyro[2]) << 8) | gyro[3];
	 output[2]=(((int)gyro[4]) << 8) | gyro[5];
}

Called as:

getGyro()
someVariable = output[0]; //or whatever you want to do with it

If you wanted to be really clever, you could do this:

In the header

typedef union{
  byte array[2];
  int integer;
} GyroData;

class itg3200
{
private:
	 GyroData output[3];
protected:
	 ...

In cpp:

void itg3200::getGyro(){
	 read(GYRO_OUT,6);
	 for(byte i = 0, j = 0; i < 3; i++,j+=2){
	 	 output[i].array[0]=gyro[j+1];
	 	 output[i].array[1]=gyro[j];
	 }
}

When used:

	 getGyro();
	 something = output[0].integer; //just an example of how to use the integer value.

In this situation unions are especially useful as they have a much smaller footprint compared to:
x = y<<8 + z;
which takes at least 8 clock cycles (possibly 25 depending on the compiler setting), compared to 2 for the union. (the avr has to perform 8 left shifts).

(I haven't compiled this, so I may have made a mistake somewhere, but the principal is right.)

Thanks a lot for the info. Gave me a lot of good ideas, mostly about the efficiency of unions.

RobertEagle

The union method is becoming very popular, avoids nasty casts with pointers and provides a nice OO syntax.

Here is a type safe method.

template< typename _Type > union Serializer{
  _Type  value;
  byte    data[ sizeof( _Type ) ];
};

//You would use like
class itg3200
{
private:
	 Serializer< int > output[3];
protected:
	 ...

If you don't actually need to access the data as an integer, you could use a struct rather than a union.

And it proves that people are just subjective

Speak for yourself! :stuck_out_tongue_closed_eyes: