Problems with my first class

Hello,

I am a beginner in Arduino and am currently trying out the classes. However, when compiling the code I get this error:

C:\Users\adria\Documents\Arduino\test scetches\sketch_apr13a\sketch_apr13a.ino:3:9: error: expected initializer before 'leftLED'

  • MyClass leftLED(13);*
  •     ^~~~~~~*
    

C:\Users\adria\Documents\Arduino\Testsketches\sketch_apr13a\sketch_apr13a.ino: In function 'void loop()':
C:\Users\adria\Documents\Arduino\test scetches\sketch_apr13a\sketch_apr13a.ino:11:3: error: 'leftLED' was not declared in this scope

  • leftLED.myFunction(1000);*
  • ^~~~~~~*

Exit status 1

Compilation error: expected initializer before 'leftLED'

Here is my Code:
MyClass.h

#ifndef MyClass_h
#define MyClass_h

#include "Arduino.h"

class MyClass {
  public:
    MyClass(int pin);
    void myFunction(int blinkrate);
  private:
    int _pin;
}

#endif

MyClass.cpp

#include "Arduino.h"
#include "MyClass.h"

MyClass::MyClass(int pin) {
  pinMode(pin, OUTPUT);
  _pin = pin;
}

void MyClass::myFunction(int blinkrate) {
  digitalWrite(_pin, HIGH);
  delay(blinkrate);
  digitalWrite(_pin, LOW);
  delay(blinkrate);
}

My Arduino Scetch:

#include <MyClass.h>

MyClass leftLED(13); 


void setup() {
 
}

void loop() {
  leftLED.myFunction(1000);
}

I saved the source code and the header file in the libaries folder.
I would be very grateful for your help!

You are missing a semi Colon at the end of the class declaration in the .h

class MyClass {
  public:
    MyClass(int pin);
    void myFunction(int blinkrate);
  private:
    int _pin;
}; // <==== add a semi colon here

Side note:

It’s a bad idea to set the pinMode in the constructor as the constructor (for global variables) is called very early in the code before main() and setup() are called. On some boards that means the arduino configuration process could undo your pinMode().

Typically one add a begin() method where this is handled and you call begin() in your instance in the setup.

Also use initializer lists for your variables in the constructor it’s the way to go

class MyClass {
  public:
    MyClass(byte pin) : _pin(pin) {} // no need to define it in the .cpp it does nothing else 
    void begin();
    void myFunction(int blinkrate);

  private:
    byte _pin;
}; 

Thanks a lot! How could I be so blind. It was the messing semicolon...
And thank you for your tip with the begin function!

If you have verbose output for compilation turned on then when the error is reported there is a message suggesting the cause of the problem

it never happened to anyone before... :innocent: :slight_smile:

Then, is it also probable that pin assignment task (13 ----> ledPin) be undone?

class DigitalIo  //Class Name (DigitalIO) is declared/created using class keyword
{
  private:
    int ledPin;  //variable can only be accessed by the functions under public: specifier

  public:
    DigitalIo(int powerpin): ledPin(powerpin) {} //inline constructor to initialize ledPin
    void ioDir();  //member function
    void ledON();
    void ledOFF();
};

DigitalIo led(13);  //led is called object of type DigitalIO

void setup()
{
  Serial.begin(9600);
  led.ioDir();                  //setting up the direction of IO line(13) as output
}
..........

why would that be? it's an instance variable so it will be assigned and keep the value 13.

this class seems to offer an ioDir() function that is probably equivalent to the begin() function I was referring to


the issue is more if you do a pinMode() call in the constructor as the initialisation phase of the board in main() could undo it on some boards (see this bug for example with some button libraries)

1 Like

I have given the name led.ioDir() instead of led.begin() to stay away (conceptually) from Serial.begin().

I would have thought that conceptually you would want to use begin as the function name because that is what it does

2 Likes

You mean -- led.begin() is more close to the intended meaning than led.ioDir(). I will revise my sketch using led.begin().

void DigitalIo::ioDir()   //member function definition; :: (double colon) is calld scope resolution operator
{
  pinMode(ledPin, OUTPUT);
}

===>

void DigitalIo::begin()   //member function definition; :: (double colon) is calld scope resolution operator
{
  pinMode(ledPin, OUTPUT);
}

Yes

1 Like

have you ever seen negative pin numbers?
use an uint8_t instead of the int

see ArduinoCore-avr/cores/arduino/wiring_digital.c at master · arduino/ArduinoCore-avr · GitHub

int is almost a vocabulary and is implied to cover the positive range: 0 to 32767.

What is that, exactly? A new form of int that has the range of 0 to 32767 is news to me.

Yes that’s very common in Arduino land.

And for the type of the _pin variable look at the signature of pinMode()

So going for a byte / uint8_t would make sense

I mean --
for any variable (to be holding a numerical value), almost all the pupil immediately declare an int type variable as if they will never encounter any negative number in their process. For example, for the unipolar ADC of the Arduino UNO, it is very common to see this declarartion:

int y = ananlogRead(A0);

But, the above should be --

unsigned int y = analogRead(A0);

From Arduino Referece Manual, we have:

pinMode(pin, mode)

Parameters

pin: the Arduino pin number to set the mode of.
mode: INPUT, OUTPUT, or INPUT_PULLUP.

The arguments of the piMode() function expect direct values.

Not sure what a direct value is in c++ :slight_smile:
The doc just forgot to mention the type … as they say number you can assume they mean some sort of numerical value may be on the very secret KingsCross board the is a pin Nine and Three-Quarters and so you can secretly do

const float poudlardExpressPin = 9.75;
…
pinMode(poudlardExpressPin, OUTPUT);
1 Like

Pins are countable; hence, there indices are non-fractional like: 0, 1, 2, ..., 19 for Arduino UNO.

What does countable mean? PinMode expects a number. They did not say it was an integer…

Anyway that’s another example of the limitations of the documentation

2 Likes