2

Code

(I've omitted much of the code, and left just the outline and code probably relating to the error.)

SelfDrivingCar.ino

#include "JKMain.h"
void setup() { JKMain::setup(); }
void loop() { JKMain::loop(); }

JKMain.h

#include "JKMotors.h"    
class JKMain
{
  static JKMotors motors;
public:
  static void setup();
  static void loop();
};

JKMain.cpp

#include "JKMain.h"
#include "JKPin.h"
const int leftMotorStraightSpeed = 100;
const int rightMotorStraightSpeed = 100;
const int leftMotorTurnSpeed = 150;
const int rightMotorTurnSpeed = 150;
const int turn90Time = 700;
void JKMain::loop() { }
void JKMain::setup()
{
  motors(JKPin::LeftMotorSpeed, JKPin::LeftMotorDirectionBit1, JKPin::LeftMotorDirectionBit2,
    JKPin::RightMotorSpeed, JKPin::RightMotorDirectionBit1, JKPin::RightMotorDirectionBit2,
    leftMotorStraightSpeed, rightMotorStraightSpeed,
    leftMotorTurnSpeed, rightMotorTurnSpeed, turn90Time);
}

JKMotors.h

class JKMotors
{
private:
  const int leftMotorSpeedPin;
  const int leftMotorDirectionBit1Pin;
  const int leftMotorDirectionBit2Pin;
  const int rightMotorSpeedPin;
  const int rightMotorDirectionBit1Pin;
  const int rightMotorDirectionBit2Pin;
  const int leftMotorStraightSpeed;
  const int rightMotorStraightSpeed;
  const int leftMotorTurnSpeed;
  const int rightMotorTurnSpeed;
  const int turn90Time;
  void setSideDirection(JKDirection _side, JKDirection _direction);
public:
  JKMotors(const int lmsp, const int lmdb1p, const int lmdb2p,
    const int rmsp, const int rmdb1p, const int rmdb2p,
    const int lmss, const int rmss, const int lmts, const int rmts, const int t90t);
};

JKMotors.cpp

#include "JKMotors.h"
#include "Arduino.h"
JKMotors::JKMotors(const int lmsp, const int lmdb1p, const int lmdb2p,
    const int rmsp, const int rmdb1p, const int rmdb2p,
    const int lmss, const int rmss, const int lmts, const int rmts, const int t90t):
      leftMotorSpeedPin(lmsp), leftMotorDirectionBit1Pin(lmdb1p), leftMotorDirectionBit2Pin(lmdb2p),
      rightMotorSpeedPin(rmsp), rightMotorDirectionBit1Pin(rmdb1p), rightMotorDirectionBit2Pin(rmdb2p),
      leftMotorStraightSpeed(lmss), rightMotorStraightSpeed(rmss), leftMotorTurnSpeed(lmts), rightMotorTurnSpeed(rmts), turn90Time(t90t)
{
  pinMode(leftMotorSpeedPin, OUTPUT);
  pinMode(leftMotorDirectionBit1Pin, OUTPUT);
  pinMode(leftMotorDirectionBit2Pin, OUTPUT);
  pinMode(rightMotorSpeedPin, OUTPUT);
  pinMode(rightMotorDirectionBit1Pin, OUTPUT);
  pinMode(rightMotorDirectionBit2Pin, OUTPUT);
}

JKPin.h

#include "Arduino.h"
struct JKPin
{
  // Ultrasonic
  static const int UltrasonicEcho = A4;
  static const int UltrasonicTrig = A5;

  // Servo
  static const int ServoSignal = 10;

  // Motor
  static const int LeftMotorSpeed = 5;
  static const int LeftMotorDirectionBit1 = 7;
  static const int LeftMotorDirectionBit2 = 6;
  static const int RightMotorSpeed = 3;
  static const int RightMotorDirectionBit1 = 8;
  static const int RightMotorDirectionBit2 = 9;
};

Notes

I wouldn't worry too much about the SelfDrivingCar.ino file. I had it "encapsulated" with JKMain.h. Also, don't concentrate on JKPins.h, as it is mostly "factual" information likely unrelated to the problem.


Error

sketch/JKMain.cpp: In static member function 'static void JKMain::setup()':

JKMain.cpp:19: error: no match for call to '(JKMotors) (const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&)' leftMotorTurnSpeed, rightMotorTurnSpeed, turn90Time);

exit status 1

no match for call to '(JKMotors) (const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&)'


Request

As far as I see, I do indeed have the constructor that the error claims I lack. What's wrong with my code?


Update

(reply to jantje)

I when removing static from motors, I receive a new error:

In file included from sketch/JKMain.cpp:1:0:

sketch/JKMain.h: In static member function 'static void JKMain::setup()':

JKMain.h:10: error: invalid use of member 'JKMain::motors' in static member function

JKMotors motors;

JKMain.cpp:16: error: from this location

motors(JKPin::LeftMotorSpeed, JKPin::LeftMotorDirectionBit1, JKPin::LeftMotorDirectionBit2,

exit status 1

invalid use of member 'JKMain::motors' in static member function

4
  • In your question you have two of JKMain.h - is one of them supposed to be JKMain.cpp?
    – Nick Gammon
    Dec 5, 2016 at 22:16
  • static JKMotors motors; why are you making a class when you appear to be planning to have a single instance of the class? A namespace might be more appropriate and less work.
    – Nick Gammon
    Dec 5, 2016 at 22:24
  • By "the class", what are you referring to: JKMain or JKMotors?
    – Fine Man
    Dec 5, 2016 at 22:25
  • I'm referring to JKMotors, since you are making a static variable motors. If you do it like that, you have to then also make a static instance of the variable at global scope.
    – Nick Gammon
    Dec 5, 2016 at 22:34

3 Answers 3

2

The idea to embed both setup() and loop() with an OOP instance is good, but why not pushing the use of class JKMotors and class JKMain deeper by removing static variables and functions.

Step1 - use a JKMotors * in a non-static class JKMain:

The default constructor JKMain() is just used to initialize motors.

class JKMain
{
  JKMotors *motors;
public:
    JKMain() { motors = NULL; };
  void setup();
  void loop();
};

Step2 - create the motors instance in the void JKMain::setup() as proposed by @Mikael Patel

But now, the JKMotors *motors; is accessible from the non-static void JKMain::setup().

void JKMain::loop() { }
void JKMain::setup()
{
  motors = new JKMotors(JKPin::LeftMotorSpeed, JKPin::LeftMotorDirectionBit1, JKPin::LeftMotorDirectionBit2,
    JKPin::RightMotorSpeed, JKPin::RightMotorDirectionBit1, JKPin::RightMotorDirectionBit2,
    leftMotorStraightSpeed, rightMotorStraightSpeed,
    leftMotorTurnSpeed, rightMotorTurnSpeed, turn90Time);
}

Step3 - declare a global JKMain instance and call setup/loop method from static setup/loop functions.

The JKMotors *motors; is now accessible from both JKMain::setup() and JKMain::loop()functions.

JKMain glbMain;

void setup() { glbMain.setup(); }
void loop() { glbMain.loop(); }
3
  • Nice work! That compiles OK.
    – Nick Gammon
    Dec 5, 2016 at 22:40
  • I don't like static functions mixed with OOP. Enjoy C++ with your Arduino.
    – J. Piquard
    Dec 5, 2016 at 22:41
  • +1 -- Oooh. I like this way. I'll give it a checkmark once I implement it and make sure it works.
    – Fine Man
    Dec 5, 2016 at 22:44
1

I think the problem is related to the fact motors is declared as a static member which makes it a global variable. This means the constructor can not be in the setup method.
I'm not 100% sure about the format but you need something like

#include "JKMain.h"
#include "JKPin.h"
const int leftMotorStraightSpeed = 100;
const int rightMotorStraightSpeed = 100;
const int leftMotorTurnSpeed = 150;
const int rightMotorTurnSpeed = 150;
const int turn90Time = 700;
  JKMain::motors(JKPin::LeftMotorSpeed, JKPin::LeftMotorDirectionBit1, JKPin::LeftMotorDirectionBit2,
    JKPin::RightMotorSpeed, JKPin::RightMotorDirectionBit1, JKPin::RightMotorDirectionBit2,
    leftMotorStraightSpeed, rightMotorStraightSpeed,
    leftMotorTurnSpeed, rightMotorTurnSpeed, turn90Time);
void JKMain::loop() { }
void JKMain::setup()
{

}
1
  • See update to my question for my reply.
    – Fine Man
    Dec 5, 2016 at 21:43
1
void JKMain::setup()

{
  motors(JKPin::LeftMotorSpeed, JKPin::LeftMotorDirectionBit1, JKPin::LeftMotorDirectionBit2,
    JKPin::RightMotorSpeed, JKPin::RightMotorDirectionBit1, JKPin::RightMotorDirectionBit2,
    leftMotorStraightSpeed, rightMotorStraightSpeed,
    leftMotorTurnSpeed, rightMotorTurnSpeed, turn90Time);
}

You can't call a constructor like that. A constructor is either implicitly called, eg. if foo is a class:

foo bar;   // constructor for foo called

Or:

foo bar (1, 2, 3, 4);  // pass arguments to the constructor

Or even as some people do:

foo bar = foo (1, 2, 3, 4);

The last example creates a temporary instance of foo that is then copied into bar.

But what you can't do is this:

foo bar;   // make an instance of the class
bar (1, 2, 3, 4);  // call the constructor later

It's too late! The instance already exists. In your case motors is the instance of the class JKMotors. You can't call the constructor later on in the code. It doesn't make sense.

2
  • Ah, that's right. If I remember correctly, it is possible to do this if I implement operator=. Am I correct? If so, how would I implement it?
    – Fine Man
    Dec 5, 2016 at 22:38
  • J. Piquard's answer compiles OK without needing to implement operator=. He calls new to create the instance of the class (deferred because it is now a pointer) and thus we don't need operator=.
    – Nick Gammon
    Dec 5, 2016 at 22:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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