arduinoarduino-c++

C++/Arduino - pass one objects instance as a pointer(?) to another class


Forgive my ignorance with C++, I'm new here. Writing a custom class for some Arduino code.

I am using a TMC driver and library to control a motor. Simplified example:

#include <TMCStepper.h>
TMC2209Stepper driver(&Serial1, 0.11f, 0b00);

void setup() {
   driver.begin();
   driver.rms_current(2000);
   driver.microsteps(32);
}

void loop() {
   // Set motor speed to 100
   driver.VACTUAL(100);
}

However I need to store various states and whatnot and the amount of which would clog up my main code. I instead want to create a custom class which would encapsulate my variables and functions. I envision it would work something like this:

#include <TMCStepper.h>
TMC2209Stepper driver(&Serial1, 0.11f, 0b00);

#include <MyCustomController.h>
// pass "driver" as a pointer?
MyCustomController customControl(*driver);

void setup() {
   driver.begin();
   driver.rms_current(2000);
   driver.microsteps(32);
}

void loop() {
   // Set motor speed to 100
   customControl.setSpeed(100);
}

With the custom class looking something like this

class MyCustomController {
   public:
      bool someState = false;
      bool someOtherState = true;

      void setSpeed(int speed) {
         // how do I get "driver" here?
         driver.VACTUAL(speed);
      } 
}

How do I pass driver from main.cpp to my MyCustomController class and use it as an "alias", pointer(?).


Solution

  • First, you want to create a MyCustomController object that takes a driver as a constructor parameter, meaning that in order to create the object, you have to pass the driver as an argument. You can do this like so:

    class MyCustomController {
    public:
      bool someState = false;
      bool someOtherState = true;
      TMC2209Stepper* driver;
    
      MyCustomController(TMC2209Stepper* d) : driver(d) {} // <- this line here
    
      void setSpeed(int speed) {
         driver->VACTUAL(speed); // <- be careful, use "->" operator
      } 
    }
    

    This constructor (it's a constructor because it's a function with the same name of the class) takes a pointer to the driver, and save it as an object property. Since you have a pointer to the driver, you now access its property through the operator -> instead of the "." operator (or you could also do (*driver).VACTUAL(speed)).

    Now, in the main code, to pass a variable as a pointer, you don't have to use the "*" operator, but the "&" operator instead. The "*" operator access the memory location of the pointer and returns the actual variable content. The "&" operator gets the address of a variable. You want to use the "&" operator because you want to store an address in your object, and then access its memory using the "*" (or the "->") operator. So your code will be something like this:

    #include <TMCStepper.h>
    TMC2209Stepper driver(&Serial1, 0.11f, 0b00);
    
    #include <MyCustomController.h>
    // pass "driver" as a pointer?
    MyCustomController customControl(&driver); // <- passing the drive address to
                                               // the MyCustomController constructor
    
    void setup() {
       driver.begin();
       driver.rms_current(2000);
       driver.microsteps(32);
    }
    
    void loop() {
       // Set motor speed to 100
       customControl.setSpeed(100);
    }