undeclared identifier class error when using Codebender or the Arduino IDE

Hello, I have been attempting to make a class in Arduino using A classy solution | Multi-tasking the Arduino - Part 1 | Adafruit Learning System and have encountered a problem. The code throws an Undeclared Identifier error, even though they are in fact declared as far as I can tell(I know I must be missing something, but i’m not sure what is is)
note:I have also tried moving the class to below //definitions, but that made even more errors

Here is the Code

class ColorSensor
{
  //variable setup
  int rColorStrength; //gives values between 0, and 255
  int gColorStrength; // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
  int bColorStrength; //  ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
  	long OnTime;     // milliseconds of on-time
	long OffTime;    // milliseconds of off-time
  unsigned int pulseWidth; //can deal with values higher than int
  	unsigned long previousMillis;  // will store last time "void CSS()" was run
  
  
    public:
    ColorSensor(int S2, int S3, int outPin, unsigned long serialPort, long on, long off)  //  :confused: 
    {                                                                                    //  :confused: 
      Serial.begin(serialPort);
      pinMode(S2, OUTPUT);
      pinMode(S3, OUTPUT);
      pinMode(outPin, INPUT);
      
      	OnTime = on;
		OffTime = off;
		previousMillis = 0;
    }
    
    void Update()
    {
    	// check to see if it's time to change the state of the LED
    	unsigned long currentMillis = millis();
    	
    	if(currentMillis - previousMillis >= OnTime)
    	{
			previousMillis = currentMillis;  // Remember the time
    	}
    	else if(currentMillis - previousMillis >= OffTime)
    	{
    		previousMillis = currentMillis;   // Remember the time
    		CSS(); //run loop
    	}
    }
    
    void CSS() //Color Sensor Serial
    {
    //to find red
    digitalWrite(S2, LOW);
    digitalWrite(S3, LOW);
    pulseWidth - pulseIn(outPin, LOW);
    rColorStrength = pulseWidth/400. -1;
    rColorStrength = (255- rColorStrength);
    //to find Green
    digitalWrite(S2, HIGH);
    digitalWrite(S3, HIGH);
    pulseWidth - pulseIn(outPin, LOW);
    gColorStrength = pulseWidth/400. -1;
    gColorStrength = (255- gColorStrength);
    //to find Blue
    digitalWrite(S2, LOW);
    digitalWrite(S3, HIGH);
    pulseWidth - pulseIn(outPin, LOW);
    bColorStrength = pulseWidth/400. -1;
    bColorStrength = (255- bColorStrength);
    
    Serial.print(rColorStrength);
    Serial.print(" , ");
    Serial.print(gColorStrength);
    Serial.print(" , ");
    Serial.print(bColorStrength);
    Serial.print("");
    }
};

//Definitions
    int//Proximity Sensor Definitions
     SoIn=1, //Sonar input  
     SoNi=2; //Sonar output
  
     ColorSensor CSS1(7, 8, 4, 115200, 100, 500); //ColorSensor                              //  :confused: 
     //S2, S3, outPin, serialPort, on, off                                                  //  :confused: 


//Classes -> Must be located after Definitions

//Setup
void setup()
  {
    Serial.begin(57600);
     pinMode(SoIn, INPUT); pinMode(SoNi, OUTPUT); //all things sonar
  }


//-------------------------------The Plan-------------------------------------//
//0)ignore the first alert from sonar caused by leaving the ramp
//1)go forward until wall
// a)check left                                  |===================|
//   i)if wall present, LW==0                    ||    The  Plan    ||
//   ii)if wall absent, LW==1                    |===================|
// b)check right
//   i)if wall present, RW==0
//   ii)if wall absent, RW==1
// c)decide weather to check color sensor
//   i)L==2 (after 3rd turn has occured only)
//     1)check color sensor and report result to variable "COLOR"
//   ii)L><2 
//     1)ignore color sensor(this leaves "COLOR" equal to 0)
// d)decide what direction to turn
//   i)RW==LW && COLOR==0, freak out(this isn supposed to be able to happen)
//   ii)RW>LW && COLOR==0, turn robot right 90 degrees and L++
//   iii)RW<LW && COLOR==0, turn robot left 90 degrees and R++
//   iv)COLOR==BLUE, execute actions for blue
//   v) COLOR==RED, execute actions for red
//-----------------------------------------------------------------------------//
void loop()
{
	CSS1.Update();
}

//==================//
// all color sensor //
//==================//
void CoMa() //main color sensor loop
{
  
}

//==================//
//     all sonar    //
//==================//
void SoMa() //main sonar loop
{
  
}

//===================//
//all motor Functions//
//===================//
void RoRi() //Robot right
{
  
}

void RoLe() //Robot left
{
  
}

void RoFo() //robot forward
{
  
}
  
void LiUp() //Lift up
{
  
}

void LiDo() //Lift down
{
  
}

void LoRi() //look right
{
  
}
  
void LoLe() //look left
{
  
}

void LoFo() //look forward
{
  
}

========================
Here is the error from the Arduino IDE:

/Users/derekgilhousen/Documents/Arduino/sketch_mar31b/sketch_mar31b.ino: In member function 'void ColorSensor::CSS()':
sketch_mar31b:45: error: 'S2' was not declared in this scope
     digitalWrite(S2, LOW);
                  ^
sketch_mar31b:46: error: 'S3' was not declared in this scope
     digitalWrite(S3, LOW);
                  ^
sketch_mar31b:47: error: 'outPin' was not declared in this scope
     pulseWidth - pulseIn(outPin, LOW);
                          ^
exit status 1
'S2' was not declared in this scope

========================
Here is the error from code bender:

(sketch file) DGApproved Maze follower main code.ino:45:18: error: use of undeclared identifier 'S2'
    digitalWrite(S2, LOW);
                 ^
(sketch file) DGApproved Maze follower main code.ino:46:18: error: use of undeclared identifier 'S3'
    digitalWrite(S3, LOW);
                 ^
(sketch file) DGApproved Maze follower main code.ino:47:26: error: use of undeclared identifier 'outPin'
    pulseWidth - pulseIn(outPin, LOW);
                         ^
(sketch file) DGApproved Maze follower main code.ino:51:18: error: use of undeclared identifier 'S2'
    digitalWrite(S2, HIGH);
                 ^
(sketch file) DGApproved Maze follower main code.ino:52:18: error: use of undeclared identifier 'S3'
    digitalWrite(S3, HIGH);
                 ^
(sketch file) DGApproved Maze follower main code.ino:53:26: error: use of undeclared identifier 'outPin'
    pulseWidth - pulseIn(outPin, LOW);
                         ^
(sketch file) DGApproved Maze follower main code.ino:57:18: error: use of undeclared identifier 'S2'
    digitalWrite(S2, LOW);
                 ^
(sketch file) DGApproved Maze follower main code.ino:58:18: error: use of undeclared identifier 'S3'
    digitalWrite(S3, HIGH);
                 ^
(sketch file) DGApproved Maze follower main code.ino:59:26: error: use of undeclared identifier 'outPin'
    pulseWidth - pulseIn(outPin, LOW);
                         ^
9 errors generated.

S2 is a parameter for the constructor but is otherwise undeclared which means no "S2" exists in the CSS method.

I don't use classes (yet) but look at ColorSensor. Inside ColorSensor you use S2 and S3 and outPin, which is ok because you have given those as parameters at the top of the function.

CSS, on the other hand, has no parameters and so does not understand what S2 S3 etc is.

Thank you for your replies, I appreciate it, and I am new to dealing with classes myself.

    public:
    ColorSensor(int S2, int S3, int outPin, unsigned long serialPort, long on, long off)  
    {                                                                                   
      Serial.begin(serialPort);
      pinMode(S2, OUTPUT);
      pinMode(S3, OUTPUT);
      pinMode(outPin, INPUT);
      
      	OnTime = on;
		OffTime = off;
		previousMillis = 0;
    }

//From the flasher tutorial

public:
  Flasher(int pin, long on, long off)
  {
	ledPin = pin;
	pinMode(ledPin, OUTPUT);     
	  
	OnTime = on;
	OffTime = off;
	
	ledState = LOW; 
	previousMillis = 0;
  }

--aren't the above defined/declared here?

  ColorSensor CSS1(7, 8, 4, 115200, 100, 500); //ColorSensor
          //S2, S3, outPin, serialPort, on, off

 Flasher led1(12, 100, 400);    //from the flasher tutorial

I did try declaring the variables above the class by defining the variables themselves, and it removed the errors, but sort of messed up the point of making a class in the first place...

Read this...
http://www.arduino.cc/en/Reference/Scope

The scope of S2 is inside the constructor (ColorSensor::ColorSensor). It does not exist anywhere else.

Also, you should not be calling pinMode() inside the constructor. Your constructor may be called before the hardware is ready.

DGApproved:
Thank you for your replies, I appreciate it, and I am new to dealing with classes myself.

I did try declaring the variables above the class by defining the variables themselves, and it removed the errors, but sort of messed up the point of making a class in the first place...

You have defined int rColorStrength,gColorStrength. bColorStrength;

and these will exist as long as the object exists. Do the same with m_S1, m_S3 m_outPin and so on.

Then inside ColorSensor store the parameters as follows:

    ColorSensor(int S2, int S3, int outPin, unsigned long serialPort, long on, long off) 
    {   
      m_S2 = S2 ;
      m_S3 = S2 ;
  ...

Now inside CSS refer to m_S2, m_S3 etc. So ColorSensor sets them up, and CSS uses them.

By the way the "m_" is a way of saying "this is a member variable" and you'd probably do well to use the same with...

int m_rColorStrength,m_gColorStrength m_bColorStrength;

else it is difficult to see which variables are part of a class and which are not.

Thank you for the reply giovanniguerra,
What you said has worked, and the code compiles and uploads successfully. :slight_smile:

For some reason, However, any serial print commands I put inside of a secondary loop which is inside of a class fail to execute. Do you know what might be causing this?

Updated code:

//****************************** Classes *******************************************
	 class ColorSensor 
	 {
  //variable setup                          // "m_" is used to classify item as a member variable
  int m_rColorStrength;                     //
  int m_gColorStrength;                     //gives values between 0, and 255
  int m_bColorStrength;                     //
  unsigned int m_pulseWidth;                //can deal with values higher than int
  //Time management
	long m_OnTime;                      // milliseconds of on-time
	long m_OffTime;                     // milliseconds of off-time
  	unsigned long m_previousMillis;     // will store last time loop was run
  //Variable initiation for ColorSensor
	int m_S2, m_S3, m_outPin;           //ColorSensor pin setup
    unsigned long m_serialPort;             //colorsensor SerialPort setup
    long m_on, m_off;                       //Time Management(in miliseconds)
	
  
    public:
    ColorSensor(int m_S2, int m_S3, int m_outPin, unsigned long m_serialPort, long m_on, long m_off)
    {
      pinMode(m_S2, OUTPUT);           //
      pinMode(m_S3, OUTPUT);           //Pin Setup
      pinMode(m_outPin, INPUT);        //
	  
        Serial.begin(m_serialPort);    //SeialPort initialization
      
      	m_OnTime = m_on;               //
        m_OffTime = m_off;             //Time Setup
        m_previousMillis = 0;	       //
    }
    
    void Update()
    {
    	unsigned long m_currentMillis = millis();

    	if(m_currentMillis - m_previousMillis == m_OffTime)
    	{
                Serial.print("The time is: ");            //
                Serial.println(m_currentMillis);          //Print time since program was run
                m_previousMillis = m_currentMillis;       // Remember the time
                CSS();                                    //Run CSS to find and serialprint colorsensor info
    	}
    }
	void CSS()
	{    			
			//to find red
    	digitalWrite(m_S2, LOW);
		digitalWrite(m_S3, LOW);
		m_pulseWidth - pulseIn(m_outPin, LOW);
		m_rColorStrength = m_pulseWidth/400. -1;
   		m_rColorStrength = (255 - m_rColorStrength);
   			//to find Green
   		digitalWrite(m_S2, HIGH);
   		digitalWrite(m_S3, HIGH);
   		m_pulseWidth - pulseIn(m_outPin, LOW);
   		m_gColorStrength = m_pulseWidth/400. -1;
   		m_gColorStrength = (255- m_gColorStrength);
   			//to find Blue
   		digitalWrite(m_S2, LOW);
   		digitalWrite(m_S3, HIGH);
   		m_pulseWidth - pulseIn(m_outPin, LOW);
   		m_bColorStrength = m_pulseWidth/400. -1;
   		m_bColorStrength = (255- m_bColorStrength);
   
		Serial.print(m_rColorStrength);
		Serial.print(" , ");
    	        Serial.print(m_gColorStrength);
    	        Serial.print(" , ");
    	        Serial.print(m_bColorStrength);
    	        Serial.println("");
	}
};
	 //==============================================================
	 //ColorSensor CSS1(S2, S3, outPin, serialPort, on, off);  //Class initiation
	   ColorSensor CSS1(7, 8, 4, 115200, 10, 10);  //Class initiation
//***************************** Definitions ******************************************

//******************************** Setup *******************************************
void setup()
  {
     pinMode(11, OUTPUT); //BLUE
  }
//******************************* Main Loop ****************************************
void loop()
{
        digitalWrite(11, HIGH);
	CSS1.Update();
        digitalWrite(11, LOW);
        delay(10);
}
//***************************** Secondary Loops ***********************************


//===================//
//   Drive Motor(2)  //
//===================//
void RoRi() //Robot right
{
  
}

void RoLe() //Robot left
{
  
}

void RoFo() //robot forward
{
  
}
  
void LiUp() //Lift up
{
  
}

void LiDo() //Lift down
{
  
}

That question about the serial print needs to go inside a new post. Else titles don't reflect contents and we all get confused.

Also the indenting of you code is, er, very individual. You need to keep it more standard. It helps you and others know where if and for blocks start and stop.

  public:
  ColorSensor(int S2, int S3, int outPin, unsigned long serialPort, long on, long off) 
  {

As others have mentioned, the constructor gets S2 and S3 but doesn't put them anywhere. One way to fix this is:

  int m_S2;
  int m_S3;
  public:
  ColorSensor(int S2, int S3, int outPin, unsigned long serialPort, long on, long off) 
  {                                                                                   
    m_S2 = S2;
    m_S3 = S3;

Another way to fix this is using constructor syntax:

  int m_S2;
  int m_S3;
  public:
  ColorSensor(int S2, int S3, int outPin, unsigned long serialPort, long on, long off) :
    m_S2(S2),
    m_S3(S3)
  {

The syntax looks a little weird, but that's because it's mainly meant for constructing objects by composition or inheritance:

class A {
  A(int a, int b) { … construct an A … }
}

// composition
class B {
  A my_a;
  B(int a, int b, int c) : my_a(a,b) {
    … construct a B …
  }
}

// inheritance
class C : A {
  B(int a, int b, int c) : A(a,b) {
    … construct a C …
  }
}

For more fun with arduino and objects, see my page on the topic.

However, any serial print commands I put inside of a secondary loop which is inside of a class fail to execute. Do you know what might be causing this?

I don't even understand the question. Code has to be in functions. Functions that belong to a class are often referred to as methods. Code isn't just "inside a class".

There are no "secondary" operations. There can be loops in functions. There can be loops inside of loops. There can not be "a secondary loop" anywhere.

You really should separate the class definition from the class implementation. The definition belongs in a .h file; the implementation belongs in a .cpp file.

You have NO idea whether the hardware is ready (it probably is NOT) when your constructor gets called. You should, therefore NOT be calling code, like pinMode(), that diddles with the hardware, in your constructor.

The argument to Serial.begin() is NOT a port. The name you assign to the argument is complete nonsense.

Thank you all for your replies, the have all been extraordinarily helpful:)

giovanniguerra:
That question about the serial print needs to go inside a new post. Else titles don't reflect contents and we all get confused.

I can agree with that

giovanniguerra:
Also the indenting of you code is, er, very individual. You need to keep it more standard. It helps you and others know where if and for blocks start and stop.

Yeah, I was using codebender, and tabs transfer over as spaces, I will fix the formatting next time. I appreciate the constructive criticism :slight_smile:

PaulMurrayCbr:
For more fun with arduino and objects, see my page on the topic.

Thank you for the link, This page contains a wealth of information which is generally not easy to get to while in high school(or for me at least), I shall be using it in the near future. (:

PaulS:
I don't even understand the question. Code has to be in functions. Functions that belong to a class are often referred to as methods. Code isn't just "inside a class".

There are no "secondary" operations. There can be loops in functions. There can be loops inside of loops. There can not be "a secondary loop" anywhere.

You really should separate the class definition from the class implementation. The definition belongs in a .h file; the implementation belongs in a .cpp file.

You have NO idea whether the hardware is ready (it probably is NOT) when your constructor gets called. You should, therefore NOT be calling code, like pinMode(), that diddles with the hardware, in your constructor.

The argument to Serial.begin() is NOT a port. The name you assign to the argument is complete nonsense.

Sorry about the incorrect terminology I used, I am still a bit new at this sort of thing... I see what you are saying, and will certainly take it into consideration. Also, yes, the name was a bit rushed, and I really should change it to avoid confusion.