0

I have this:

class Person{
public:
    int age;
};

Person p;
p.age;

void setup() { ... }

void loop() { ... }

And I got this error:

Compiling 'MyProgram' for 'Arduino Mega w/ ATmega2560 (Mega 2560)'
MyProgram.ino:18:1: error: 'p' does not name a type
Error compiling

But is I use the Person instance inside setup or loop functions it compiles find.

void setup() {
    // initialize digital pin 13 as an output.
    Person p;
    p.age;
}

I got this:

Compiling 'MyProgram' for 'Arduino Mega w/ ATmega2560 (Mega 2560)'
Binary sketch size: 4,674 bytes (used 2% of a 253,952 byte maximum) (3.45 secs)
Minimum Memory Usage: 428 bytes (5% of a 8192 byte maximum)

What is the different? Why the instance only can be used into the blocks?

I also declared a file with a simple class and then create a instance of it class outside the blocks and I got the same error. If I put the instance inside the blocks it works. So, any tips?

2

As you have already noticed, you cannot call methods of a class, nor access its properties, outside a "block" (as you call it). More specifically, you can only perform "programatical" operations from within a function. Anything outside a function (known as the global scope) is purely for declaration and initialization of variables and types, etc.

Any class variables declared in the global scope have their constructor executed before the rest of the program (even before setup) gets run. However, setup is not the first function to be called at startup.

Anything you put into a constructor has to take into account the fact that anything might be happening between the constructor being called and the object instance actually being used. Things like pinMode and digitalWrite are unsafe to use in a constructor, since there is a chance they may be negated during the startup. That is why the majority of Arduino classes have a .begin() method which is called from setup().

The proper method for using classes with pin control and similar operations is:

  1. The constructor takes the pins to use
  2. The constructor saves those pins in variables
  3. The begin() method is called in setup()
  4. The pins are configured appropriately.

For example:

class myClass {
    private:
        int _myPin;
    public:
        myClass(int pin) : _myPin(pin) {}

       void begin() {
            pinMode(_myPin, OUTPUT);
            digitalWrite(_myPin, HIGH);
        }
};

myClass p(4);

void setup() {
    p.begin();
}

void loop() {
}

The object instance p is in the global scope and can be referenced from any function. The pin is configured only when setup() is run.

The startup sequence, more specifically, is typically this:

  1. The memory used by global and static variables is "zeroed".
  2. Any pre-defined variable values (BSS) are copied from flash into RAM.
  3. Any object constructors are called.
  4. The main() function is called (main startup function).
  5. The init() function is called which configures the Arduino platform.
  6. The initVariant() function is called which performs any board specific setup routines.
  7. USB is configured on the boards that have it
  8. Your setup() function is called.
  9. Your loop() function is called.
  10. The serialEvent() system runs if defined.
  11. Go to 10.

As you can see quite a lot happens between the constructor being called and setup() being called, and you cannot reliably predict what that might be. Some boards may do nothing more than configure interrupts and enable timers (for things like delay and millis), but other boards may configure IO pins to default settings (especially more complex boards with multiple functions per IO pin), so really the only safe operations you can perform in a constructor are operations which act directly on the internals of the class itself. Anything outside the scope of the class could be changed before you come to use it.

2

All code intended to be executed must be inside a function block in C++.

  • So, I can create an object instance but if I want to use it I have to invoke the functions inside the block? Is that correct? I am asking because right now I cannot test the arduino project. – Robert Jun 2 '15 at 3:04
  • That is correct. You can declare and initialize an object in the global scope, but you cannot call its methods or access its fields. – Ignacio Vazquez-Abrams Jun 2 '15 at 3:05
  • Having said that, it is possible to create additional memory segments that are executed prior to main(), but I don't know if the Arduino IDE will handle them appropriately. – Ignacio Vazquez-Abrams Jun 2 '15 at 3:06
  • I am trying to create a simple instance before the setup() and loop() blocks. Inside the instance I configure some pins to the output mode. But Arduino show a wrong behavior. But if I configure this pins into the setup blocks the Arduino show me the right behavior. I am really confuse. Because I want to use some class to reuse some functions. – Robert Jun 2 '15 at 6:34
  • Then put the code to configure the pins in the constructor block. – Ignacio Vazquez-Abrams Jun 2 '15 at 6:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.