Getting error: " 'classNameHere' was not declared in this scope" when separating code in class outside of the main program

Hello, I am new to arduino object oriented programming. So I stumbled across a video about object oriented programming and making the project more structured. In the said tutorial the guy used just header files for storing the classes. So I did the same, when I added the first class everything was working, because I still had the dependent code in the main program. But when I separated the dependent code in a second class I started getting: FiguresMovement.h:18:5: error: 'motorsControl' was not declared in this scope motorsControl.moveForward(_shortDuration); ^~~~~
My main program is this:
Main program
My MotorsControl class(pasting just small bit of the code):
MotorsControlH
My FiguresMovement class(pasting just small bit of the code):
FiguresMovementH
As you can see my FigruresMovement class is dependent on the MotorsControl class as it uses the methods from motorsControl. By my noobie logic including the classes one after another in the main program should not break the program, because the motorsControl object of class MotorsControl will be already defined before use. As you can see the order of including and instancing the classes is first-MotorsControl, second-FiguresMovement. Can somebody help me with that problem? Why am I getting "function was not declared in this scope"? How can I fix this error?

Please post your code.
Use code tags.
Please post your error message(s).
Use code tags.

TIA

I already posted my code in the pastebin links, but okay I will post them in reply too.
My main program:

#include "MotorsControl.h"
#include "FiguresMovement.h"
//pins for left motor
int pwmPinLeftMotor = 10;
int outputPinTwo = 2;    //signal pin for forward
int outputPinThree = 3;  //signal pin for backward
//pins for right motor
int pwmPinRightMotor = 6;
int outputPinFour = 4;  //signal pin for forward
int outputPinFive = 5;  //signal pin for backward
int motorSpeed = 50;
int SHORT_DURATION = 1000;
int MEDIUM_DURATION = 2000;
int LONG_DURATION = 5000;
int EXTRA_LONG_DURATION = 10000;
byte receivedData;
 
 
/////////////////////////////////////////////////////////////
 
MotorsControl motorsControl(pwmPinLeftMotor, pwmPinRightMotor, outputPinTwo, outputPinThree, outputPinFour, outputPinFive, motorSpeed);
FiguresMovement figuresMovement(SHORT_DURATION, MEDIUM_DURATION, LONG_DURATION, EXTRA_LONG_DURATION);
 
void setup() {
 
  //setting pins to be outputing signal to the TB6612FNG
  Serial.begin(9600);
}
 
////////////////////////////////////////////////////////
 
void loop() {
  if (Serial.available() > 0) {
    receivedData = Serial.read();
    switch (receivedData) {
      case 49:
        figuresMovement.pawnMovement();
        Serial.print('1');
        break;
      case 50:
        figuresMovement.bishopMovement();
        Serial.print('1');
        break;
      case 51:
        figuresMovement.kingMovement();
        Serial.print('1');
        break;
      case 52:
        figuresMovement.rookMovement();
        Serial.print('1');
        break;
      case 53:
        figuresMovement.knightMovement();
        Serial.print('1');
        break;
      case 54:
        figuresMovement.queenMovement();
        Serial.print('1');
        break;
    }
  }
}

My MotorsControl.h(class):

class MotorsControl {
  int _pwmPinLeftMotorVar;
  int _pwmPinRightMotorVar;
  int _outputPinTwoVar;
  int _outputPinThreeVar;
  int _outputPinFourVar;
  int _outputPinFiveVar;
  int _motorSpeedVar;
 
public:
  MotorsControl(int pwmPinLeftMotorVar, int pwmPinRightMotorVar, int outputPinTwoVar, int outputPinThreeVar, int outputPinFourVar, int outputPinFiveVar, int motorSpeedVar) {
    _pwmPinLeftMotorVar = pwmPinLeftMotorVar;
    _pwmPinRightMotorVar = pwmPinRightMotorVar;
    _outputPinTwoVar = outputPinTwoVar;
    _outputPinThreeVar = outputPinThreeVar;
    _outputPinFourVar = outputPinFourVar;
    _outputPinFiveVar = outputPinFiveVar;
    _motorSpeedVar = motorSpeedVar;
    pinMode(_pwmPinLeftMotorVar, OUTPUT);
    pinMode(_pwmPinRightMotorVar, OUTPUT);
    pinMode(_outputPinTwoVar, OUTPUT);
    pinMode(_outputPinThreeVar, OUTPUT);
    pinMode(_outputPinFourVar, OUTPUT);
    pinMode(_outputPinFiveVar, OUTPUT);
    analogWrite(_pwmPinLeftMotorVar, _motorSpeedVar);
    analogWrite(_pwmPinRightMotorVar, _motorSpeedVar);
  }
  void resetPins() {
    digitalWrite(_outputPinTwoVar, LOW);
    digitalWrite(_outputPinThreeVar, LOW);
    digitalWrite(_outputPinFourVar, LOW);
    digitalWrite(_outputPinFiveVar, LOW);
  }
 
  void moveForward(int duration) {
    digitalWrite(_outputPinTwoVar, HIGH);
    digitalWrite(_outputPinThreeVar, LOW);
    digitalWrite(_outputPinFourVar, HIGH);
    digitalWrite(_outputPinFiveVar, LOW);
    delay(duration);
  }
};

My FiguresMovement.h(class that is dependent on the MotorsControl.h):

class FiguresMovement {
  int _shortDuration;
  int _mediumDuration;
  int _longDuration;
  int _extraLongDuration;
 
public:
  FiguresMovement(int shortDuration,
                  int mediumDuration,
                  int longDuration,
                  int extraLongDuration) {
    _shortDuration = shortDuration;
    _mediumDuration = mediumDuration;
    _longDuration = longDuration;
    _extraLongDuration = extraLongDuration;
  }
  void pawnMovement() {
    motorsControl.moveForward(_shortDuration);
    motorsControl.moveBackward(_shortDuration);
    motorsControl.resetPins();
  }
};

Part of the Error Log:

FiguresMovement.h: In member function 'void FiguresMovement::pawnMovement()':
c:\Users\ivan\Documents\Arduino\chess_movement_oo\FiguresMovement.h:18:5: error: 'motorsControl' was not declared in this scope
     motorsControl.moveForward(_shortDuration);
     ^~~~~~~~~~~~~
c:\Users\ivan\Documents\Arduino\chess_movement_oo\FiguresMovement.h:18:5: note: suggested alternative: 'MotorsControl'
     motorsControl.moveForward(_shortDuration);
     ^~~~~~~~~~~~~
     MotorsControl
c:\Users\ivan\Documents\Arduino\chess_movement_oo\FiguresMovement.h: In member function 'void FiguresMovement::bishopMovement()':
c:\Users\ivan\Documents\Arduino\chess_movement_oo\FiguresMovement.h:24:5: error: 'motorsControl' was not declared in this scope
     motorsControl.moveLeftForward(_shortDuration);
     ^~~~~~~~~~~~~
c:\Users\ivan\Documents\Arduino\chess_movement_oo\FiguresMovement.h:24:5: note: suggested alternative: 'MotorsControl'
     motorsControl.moveLeftForward(_shortDuration);
     ^~~~~~~~~~~~~
     MotorsControl
c:\Users\ivan\Documents\Arduino\chess_movement_oo\FiguresMovement.h: In member function 'void FiguresMovement::kingMovement()':
c:\Users\ivan\Documents\Arduino\chess_movement_oo\FiguresMovement.h:33:5: error: 'motorsControl' was not declared in this scope
     motorsControl.moveForward(_shortDuration);
     ^~~~~~~~~~~~~
c:\Users\ivan\Documents\Arduino\chess_movement_oo\FiguresMovement.h:33:5: note: suggested alternative: 'MotorsControl'
     motorsControl.moveForward(_shortDuration);
     ^~~~~~~~~~~~~

Thanks for the help.

Your .h files seem to be missing some "#include"s themselves, and include guard macros (or "#pragma once")

What includes they are missing like #include<Arduino.h>?
I think when they get in the main program they do not need that include.
Which includes am I missing?
Can you show me an example of classes one of which depends on the other?

You've already got one: FiguresMovement depends on MotorsControl

But in the main program I include them one after the other. Also the instances are one after the other.

Can you show me where you have an instance of an object called "motorsControl"?

MotorsControl motorsControl(pwmPinLeftMotor, pwmPinRightMotor, outputPinTwo, outputPinThree, outputPinFour, outputPinFive, motorSpeed);

It is located in main program.

And there's your answer

But I cannot make an instance of MotorsControl class in my FiguresMovement class, because the MotorsControl needs input in his constructor upon initializing. I do not have the required data for the constructor in the FigursMovement class. So how do I handle this problem?

So pass it one!

So I passed MotorsControl in the constructor of FiguresMovement class:

class FiguresMovement {
  int _shortDuration;
  int _mediumDuration;
  int _longDuration;
  int _extraLongDuration;
  MotorsControl _motorsControl;
public:
  FiguresMovement(int shortDuration,
                  int mediumDuration,
                  int longDuration,
                  int extraLongDuration,
                  MotorsControl motorsControl) {
    _shortDuration = shortDuration;
    _mediumDuration = mediumDuration;
    _longDuration = longDuration;
    _extraLongDuration = extraLongDuration;
    _motorsControl = motorsControl;
  }
  void pawnMovement() {
    _motorsControl.moveForward(_shortDuration);
    _motorsControl.moveBackward(_shortDuration);
    _motorsControl.resetPins();
  }

and in the main program now looks like this:

#include "MotorsControl.h"
#include "FiguresMovement.h"
//pins for left motor
int pwmPinLeftMotor = 10;
int outputPinTwo = 2;    //signal pin for forward
int outputPinThree = 3;  //signal pin for backward
//pins for right motor
int pwmPinRightMotor = 6;
int outputPinFour = 4;  //signal pin for forward
int outputPinFive = 5;  //signal pin for backward
int motorSpeed = 50;
int SHORT_DURATION = 1000;
int MEDIUM_DURATION = 2000;
int LONG_DURATION = 5000;
int EXTRA_LONG_DURATION = 10000;
byte receivedData;


/////////////////////////////////////////////////////////////

MotorsControl motorsControl(pwmPinLeftMotor, pwmPinRightMotor, outputPinTwo, outputPinThree, outputPinFour, outputPinFive, motorSpeed);
FiguresMovement figuresMovement(SHORT_DURATION, MEDIUM_DURATION, LONG_DURATION, EXTRA_LONG_DURATION, motorsControl);

As you can see I have passed it in the instance too. But I get error saying:

c:\Users\ivan\Documents\Arduino\chess_movement_oo\FiguresMovement.h: In constructor 'FiguresMovement::FiguresMovement(int, int, int, int, MotorsControl)':
c:\Users\ivan\Documents\Arduino\chess_movement_oo\FiguresMovement.h:12:48: error: no matching function for call to 'MotorsControl::MotorsControl()'
                   MotorsControl motorsControl) {
                                                ^
In file included from c:\Users\ivan\Documents\Arduino\chess_movement_oo\chess_movement_oo.ino:1:0:
c:\Users\ivan\Documents\Arduino\chess_movement_oo\MotorsControl.h:11:3: note: candidate: MotorsControl::MotorsControl(int, int, int, int, int, int, int)
   MotorsControl(int pwmPinLeftMotorVar, int pwmPinRightMotorVar, int outputPinTwoVar, int outputPinThreeVar, int outputPinFourVar, int outputPinFiveVar, int motorSpeedVar) {
   ^~~~~~~~~~~~~

Its as if the MotorsControl is called before being passed in the FiguresMovement and it needs its constructor filled, but in the main program I call them one after the other and there the constructor is filled and I pass a filled object.

Another way to get FiguresMovement.h to understand the global motorsControl is to declare it extern near the top of FiguresMovement.h:
extern MotorsControl motorsControl;
Because it is declared elsewhere, the arguments to the constructor are not needed here.

The next bug I hit was FiguresMovement trying to use motorsControl.moveBackward(_shortDuration); but that function is not declared, just moveForward().

1 Like

Thank you a lot for the solution! You are litterally a lifesaver!!!!! The second error is not actually an error, because I did not provide the whole code, because it was gonna be one big chunk of code. And my problem was actually just making FiguresMovement "see" that MotorsControl is above it and it can use the object with its methods. THANK YOU!
Also I have another question if you have the time. Is it a good practise to put the class with full methods in an headers file? I am coming from other programming languages and I see the headers file acting as an abstract class, and then you put the actual definition in a separate cpp file. Or I can use the headers file to hold the whole definition of the class too. Also somewhere in this forum I found that it is not a good thing to place pinmode() in the class constructor, because then the hardware might not be ready and I am using pinmode before it, or there is no problem to be in the constructor. Sorry if my questions are a bit strange.

It may not be the best practice but it is not bad enough to worry about.

There are problems with using some Ardiuno library features before the library is initialized (like in the constructor of a global object). That is why many library objects have a .begin() method. I think that pinMode() is OK but 'analogWrite()' isn't since the timers will not be configured for PWM yet.

1 Like

So I changed my code, removed the pinMode(pwmPinLeftMotor, OUTPUT);
and

analogWrite(pwmPinLeftMotor, motorSpeed);

from the MotorsControl.h and putted them in the main program in the void setup().
I also made the initializations of classes below the void setup().
The code now looks like that:

#include "MotorsControl.h"
#include "FiguresMovement.h"
//pins for left motor
int pwmPinLeftMotor = 10;
int outputPinTwo = 2;    //signal pin for forward
int outputPinThree = 3;  //signal pin for backward
//pins for right motor
int pwmPinRightMotor = 6;
int outputPinFour = 4;  //signal pin for forward
int outputPinFive = 5;  //signal pin for backward
int motorSpeed = 50;
int SHORT_DURATION = 1000;
int MEDIUM_DURATION = 2000;
int LONG_DURATION = 5000;
int EXTRA_LONG_DURATION = 10000;
byte receivedData;


/////////////////////////////////////////////////////////////

void setup() {
  //setting pins to be outputing signal to the TB6612FNG
  pinMode(pwmPinLeftMotor, OUTPUT);
  pinMode(pwmPinRightMotor, OUTPUT);
  analogWrite(pwmPinLeftMotor, motorSpeed);
  analogWrite(pwmPinRightMotor, motorSpeed);
  Serial.begin(9600);
}

MotorsControl motorsControl(outputPinTwo, outputPinThree, outputPinFour, outputPinFive);
FiguresMovement figuresMovement(SHORT_DURATION, MEDIUM_DURATION, LONG_DURATION, EXTRA_LONG_DURATION);

I want to ask is that way "safer" for the timers of pwm?
I have never heard of a begin() method and idk how it works so I did this.
Thank you for the answer.

That is obviously wrong.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.