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
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.
-
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– mnj2016年09月19日 20:18:56 +00:00Commented Sep 19, 2016 at 20:18
-
@Loreno Or you can add
StepMotor & motor_right = controller_right.Motor;
aftercontroller_*
variable declaration. I guess, you can even skip thesemotor_right
/motor_left
variables as it's already inController
KIIV– KIIV2016年09月19日 20:22:36 +00:00Commented 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– mnj2016年09月19日 20:29:26 +00:00Commented Sep 19, 2016 at 20:29
-
@Loreno It's basically an alias for referenced variable.KIIV– KIIV2016年09月19日 20:31:44 +00:00Commented Sep 19, 2016 at 20:31