2

I'm doing a program for a robot and I got stuck at a weird problem: I have classes defined for my robot's internals, for example for a StepMotor. I also defined a class for a Controller, which is going to control the speed of each StepMotor.

Here's a fragment of my code:

    #include <SPI.h>
    #include <Tone.h>
    #include <Wire.h>   
    #include <LiquidCrystal_I2C.h>

    /SILNIKI KROKOWE:
    class StepMotor: public Device
    {
        public:    
            int motorPin;
            int dirPin;
            int sleepPin;
            int ForwardState;
            volatile double Speed;
            volatile int ControlValue;  //the value sent to the motor
            int MaxControlValue = 4000; //maximum ControlValue
            String Name;

            void Init ( void )
            {     
                //init
            }

            void SetSpeed ( int speed )
            {
              toneObject.play(speed);
            }

            void SetMode(bool IsOn)
            {
              if (IsOn)
                digitalWrite(sleepPin, HIGH);
              else
                digitalWrite(sleepPin, LOW);
            }

            void SetDirection ( Dir direction )
            {
    //code for setting direction
            }

        private:
          Tone toneObject;            
    };

    StepMotor motor_right;
    StepMotor motor_left;


    class Controller
    {
      public:
        ControllerType controllerType;
        double Kp;
        double Ki;
        double Kd;
        double Tp; //czas próbkowania
        volatile double e;
        volatile double e_old;
        volatile double P_result;
        volatile double I_result;
        volatile double D_result;
        StepMotor Motor;

        int Calculate ()
        {
          int Result;
     //Serial.print(Motor.Speed); HERE's THE PROBLEM
    /********************************
    /********************************
    /*******************************     
          e = MoveOrder::speed - Motor.Speed;  //Motor.Speed is always 0.00, although it's not true

             //the rest is not important
        }

        void Reset()
        {
          //reset procedure
        }

    };



    Controller controller_right;
    Controller controller_left;

    setup()
    {
       controller_right.Motor = motor_right;
       controller_left.Motor = motor_left;
    }

    ISR(TIMER5_COMPA_vect)
    {
        motor_right.ControlValue = controller_right.Calculate();
        motor_left.ControlValue = controller_left.Calculate();
        motor_right.SetSpeed(motor_right.ControlValue);
        motor_left.SetSpeed(motor_left.ControlValue);

    }

I have cut the less important parts. The rest works properly, because my robot can drive when I use SetSpeed(somevalue); The only problem is that place where I need to read current speed of my motor. In the Controller class, there's Calculate() method. In that method I want to calculate e = MoveOrder::speed - Motor.Speed; Unfortunately it can't be calculated properly, because Motor.Speed ALWAYS is 0.00 (when I display it with Serial.print(Motor.Speed) I see 0.00 all the time). It's very strange, because when I display speed of each motor (Serial.print(right_motor.Speed) or Serial.print(left_motor.Speed)) the value is correct (when the wheels are spinning, value is not 0.00).

The speed calculations are in a different function, which I didn't present here, because it would be too long - I'm sure it works, because, as I said, I can get speed values properly.

As you can see in setup(), I set each contorller's Motor porperty to the correct object. I also used volatile keyword for the properties that are used in the interrupt.

What is wrong with my code?

If the code I provided isn't enough, here's the full version: https://1drv.ms/t/s!Atl-jM_xUkz1hc1f-qYYotj-pJIgUw

I'm not sure if anyone would want to dive into it, because it's not so short.

1 Answer 1

2

My guess: controller_right.Motor = motor_right; makes a copy of motor_right. So you don't have the same class instance.

Basically Controller controller_right; calls default constructor which includes also default constructor for the StepMotor. And later all variables are copied into it by using default assigment operator, but still, it's not the same instance.

4
  • looks like you're right. So, I think I should: change StepMotor Motor in Controller class to StepMotor* Motor, to have a pointer. Then, in setup() should do controller_right.Motor = &motor_right; and controller_left.Motor = &motor_left; Am I right?
    – mnj
    Commented Sep 19, 2016 at 20:18
  • @Loreno Or you can add StepMotor & motor_right = controller_right.Motor; after controller_* variable declaration. I guess, you can even skip these motor_right/motor_left variables as it's already in Controller
    – KIIV
    Commented Sep 19, 2016 at 20:22
  • I need to be able to access motor_right and motor_left in other places (for exmple when I measure the speed of a motor and assign it to its Speed property). Your solution uses reference, right? i don't fully understand these, so I'm not sure what's the difference here. Today I can't check if the robot works correctly after applying those fixes, tomorrow I'll be able to do it and then I'll mark your answer as a proper one.
    – mnj
    Commented Sep 19, 2016 at 20:29
  • @Loreno It's basically an alias for referenced variable.
    – KIIV
    Commented Sep 19, 2016 at 20:31

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.