Cannot use custom class in sketch

Hey all,
This feels like a very silly issue, but I cannot, for the life in me get my sketch to compile. The sketch in question is a simple robot controller. Here is the code from the different files.

robot_kit.ino

#include "./Robot.h"
#include "./UltrasonicSensor.h"
#include "./Motor.h"

// Define pins
// TODO: CHANGE THESE VALUES
#define leftMotorEnable 1
#define leftMotorSwitch1 2
#define leftMotorSwitch2 3

#define rightMotorEnable 4
#define rightMotorSwitch1 5
#define rightMotorSwitch2 6

#define frontUSTrig 7
#define frontUSEcho 8

#define backUSTrig 9
#define backUSEcho 10

// Create objects
UltrasonicSensor frontUS(frontUSTrig, frontUSEcho);
UltrasonicSensor backUS(backUSTrig, backUSEcho);

Motor leftMotor(leftMotorEnable, leftMotorSwitch1, leftMotorSwitch2);
Motor rightMotor(rightMotorEnable, rightMotorSwitch1, rightMotorSwitch2);

Robot robot(frontUS, backUS, leftMotor, rightMotor);

void setup() {
    Serial.begin(9600);
}

void loop() {
    robot.drive();
}

Robot.h

#ifndef Robot_h
#define Robot_h

#include "Arduino.h"
#include "UltrasonicSensor.h"
#include "Motor.h"

class Robot {
  public:
    Robot(UltrasonicSensor usFront, UltrasonicSensor usBack, Motor motorLeft, Motor motorRight);
    Robot();
    void drive();
  private:
    UltrasonicSensor _usFront, _usBack;
    Motor _motorLeft, _motorRight;
};

#endif

Robot.cpp

#include "Robot.h"
#include "Arduino.h"
#include "UltrasonicSensor.h"
#include "Motor.h"

Robot::Robot(UltrasonicSensor usFront, UltrasonicSensor usBack, Motor motorLeft, Motor motorRight) {
  _usFront = usFront;
  _usBack = usBack;
  _motorLeft = motorLeft;
  _motorRight = motorRight;
}

// Update this method to program your robot!
void Robot::drive() {
  
}

Motor.h

#ifndef Motor_h
#define Motor_h

#include "Arduino.h"
#include "Motor.h"

class Motor {
    public:
        Motor(uint8_t enable, uint8_t input1, uint8_t input2);
        Motor();
        void setSpeed(float speed);

    private:
        // This pin turns the motor on at full speed. Using a PWM pin allows us to change the speed of the motor
        uint8_t _enable;
        // Inputs for switches of H-Bridge to change direction of the motor
        uint8_t _input1;
        uint8_t _input2;
};

#endif

Motor.cpp

#include "Motor.h"
#include "Arduino.h"

Motor::Motor(uint8_t enable, uint8_t input1, uint8_t input2) {
    _enable = enable;
    _input1 = input1;
    _input2 = input2;

    // Setup pins
    pinMode(_enable, OUTPUT);
    pinMode(_input1, INPUT);
    pinMode(_input2, INPUT);
}

void Motor::setSpeed(float speed) {
    // Make sure speed is in range [-100, 100]
    if(speed > 100 || speed < 100) {
      Serial.printf("Invalid Speed! Speeds should be between -100 and 100! Speed was %f", speed);
      return;
    }
  
    // Set H-Bridge
    if(speed < 0) {
        digitalWrite(_input1, LOW);
        digitalWrite(_input2, HIGH);
        // Set speed to positive
        speed = speed * -1;
    } else {
        digitalWrite(_input1, HIGH);
        digitalWrite(_input2, LOW);
    }

    // Map 0 to 100 to 0 to 255 to get duty cycle
    int motorPWM =  map(speed, 0, 100, 0, 255);
    
    // Set motor speed
    analogWrite(_enable, motorPWM);
}

UltrasonicSensor.h

/*
    Ultrasonic.h - Represents a ultrasonic sensor
    Created by Akshat Adsule for the STEAM org
*/


#ifndef Ultrasonic_h
#define Ultrasonic_h

#include "Arduino.h"

class UltrasonicSensor {
    public:
        UltrasonicSensor(u_int8_t trig, u_int8_t echo);
        UltrasonicSensor();
        int getDistance();
    private:
        u_int8_t _trig;
        u_int8_t _echo;
};

#endif

UltrasonicSensor.cpp

#include "UltrasonicSensor.h"
#include "Arduino.h"

UltrasonicSensor::UltrasonicSensor(u_int8_t trig, u_int8_t echo) {
    _trig = trig;
    _echo = echo;

    // Setup pins
    pinMode(_trig, OUTPUT);
    pinMode(_echo, OUTPUT);
}

int UltrasonicSensor::getDistance() {
    digitalWrite(_trig, LOW);
    delayMicroseconds(2);

    // Sets the trigPin on HIGH state for 10 micro seconds
    digitalWrite(_trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(_trig, LOW);

    // Reads the echoPin, returns the sound wave travel time in microseconds
    long duration = pulseIn(_echo, HIGH);

    // Calculating the distance
    int distance= duration*0.034/2;

    return distance;
}

The error I get when trying to compile is this:

/home/akshat/Projects/arduino/robot_kit/Robot.cpp:6: undefined reference to `_ZN16UltrasonicSensorC1Ev'
/home/akshat/Projects/arduino/robot_kit/Robot.cpp:6: undefined reference to `_ZN5MotorC1Ev'

I am not sure how this could be happening... I have included the header files in both Robot.h and Robot.cpp. I feel like i am missing something minor but I can't figure out what it is. Any help will be greatly appropriated!

Thanks in advance

Your mistake is that you cannot pass an object as a parameter to the constructor.
Passing an ordinary parameter to a function creates a copy of the variable.
A copy of the object is not automatically created.
You must use a pointer (or reference) to an object as a member variable of the class and pass a reference to the object.
You can see the hint here Arduino / C++: Pass object to constructor by reference

Another way is to create a copy constructor.
You cannot write
_usFront = usFront;
because they are objects.

1 Like

Thanks Boffin! Passing a reference to my objects solved my issue!

1 Like

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