Page 1 of 1

[NXC] How to get the real motor speed?

Posted: 06 Sep 2011, 11:13
by ricardocrl
Hey,

How can I get the real speed of the motor?

Which is not the MotorActualSpeed(). I actually don't understand why it is called "MotorActualSpeed". Isn't it a measure of the current dropped in the motor, in order to give output a regulated and constant speed? To do this control, the firmware must read the velocity to control the power imposed, right?

Isn't that accessible to the user? Or do we need to use integration, using position?

Thanks for the help!
/Ricardo

Re: [NXC] How to get the real motor speed?

Posted: 06 Sep 2011, 14:54
by mattallen37
Well, I can't help you with a FW implementation, but I personally always use a custom function to calculate it. As with most functions, I like to write them myself in NXC for better control (or at least complete understanding).

Here is something I just threw together, that seems to work fine:

Code: Select all

float MotorSpeed(byte port, unsigned int TimeFrame){
  unsigned long OriginalTime = CurrentTick();
  until (CurrentTick() == OriginalTime + 2);
  long OriginalPosition = MotorTachoCount(port);
  until (CurrentTick() == OriginalTime + 2 + TimeFrame);
  long FinalPosition = MotorTachoCount(port);
  float Time = 60000 / TimeFrame;
  long PositionDifference = FinalPosition - OriginalPosition;
  return PositionDifference * Time / 360;                                       //FinalPositon minus OrigionalPosition is the distance turned.
                                                                                //360 is the number of positions the NXT motor changes per revolution.
                                                                                //TimeFrame/60000 is putting the TimeFrame in minutes.
}

task main(){
  while(true){
    float MotorRPM = MotorSpeed(OUT_A, 100);
    ClearScreen();
    NumOut(0, LCD_LINE1, MotorRPM);
  }
}

Re: [NXC] How to get the real motor speed?

Posted: 08 Sep 2011, 01:11
by ricardocrl
Thanks for the sample!

The questions is that the FW has to calculate this to control the speed of a motor. It would be nice to have access to it, since it requires no CPU from the user program. With your solution, at least 3 ms (TimeFrame = 1) are spent.

One other question, is MotorActualSpeed in rpm? I guess not, since Philo has stated that it must go up to ~150 or more, depending on the batteries, and the regulated mode only accepts, between -100 and 100. What kind of number are these?

Re: [NXC] How to get the real motor speed?

Posted: 08 Sep 2011, 02:44
by linusa
ricardocrl wrote:It would be nice to have access to it, since it requires no CPU from the user program. With your solution, at least 3 ms (TimeFrame = 1) are spent.
Actually, you can call this speed measurement routine from another task. And then you should set TimeFrame to something higher. The method itself doesn't actually take much CPU power (it's just recording time and position at two different points in time, and then dividing by the differences).
ricardocrl wrote: One other question, is MotorActualSpeed in rpm? I guess not, since Philo has stated that it must go up to ~150 or more, depending on the batteries, and the regulated mode only accepts, between -100 and 100. What kind of number are these?
The power value should be in "degrees per 100 ms" without speed regulation. MotorActualSpeed is in the same units, but as it stands for increased firmware setpoints, it's to be treated carefully

Re: [NXC] How to get the real motor speed?

Posted: 08 Sep 2011, 03:14
by ricardocrl
linusa wrote: Actually, you can call this speed measurement routine from another task. And then you should set TimeFrame to something higher. The method itself doesn't actually take much CPU power (it's just recording time and position at two different points in time, and then dividing by the differences).
I'm afraid it's not just like that, since the line "until (CurrentTick() == OriginalTime + 2 + TimeFrame);" runs continuously, checking CurrentTick() in a loop, right? There's nothing yielding the CPU (apart from the round robin task management of course).
Well, of course it's not a heavy thing, but...
linusa wrote: The power value should be in "degrees per 100 ms" without speed regulation. MotorActualSpeed is in the same units, but as it stands for increased firmware setpoints, it's to be treated carefully
Hm, that makes much more sense, "degrees per 100ms"! Great to know. ;) But this is a measure of the input "Speed" for the speed regulation mode, right? What it seems to me is that "MotorActualSpeed()" is like a voltage value, since it oscillates depending on the resistance you put in the outshaft of the motor. I would call it "MotorActualPower", since it's an oscillating value to keep a constant speed.

Re: [NXC] How to get the real motor speed?

Posted: 08 Sep 2011, 14:03
by linusa
ricardocrl wrote: I'm afraid it's not just like that, since the line "until (CurrentTick() == OriginalTime + 2 + TimeFrame);" runs continuously, checking CurrentTick() in a loop, right? There's nothing yielding the CPU (apart from the round robin task management of course).
Well, of course it's not a heavy thing, but...
I meant the general principle.

If you need the speed of a motor at a certain time, you can do

Code: Select all

t_0 = CurrentTick();
p_0 = TachoCount(OUT_A);

// .. do stuff, whatever

delta_t = CurrentTick() - t_0;
delta_p = TachoCount(OUT_A) - p_0;
// assume delta_t > 0
speed =  delta_p / delta_t;
If you do it this way, speed will hold the average velocity in rotations per ms. I noted in a comment, delta_t must be > 0, which means "... do stuff" must take some time. Even better: The longer "do stuff" takes, the more accurate your speed-estimate will get.

Note however that this is the average speed during the time "do stuff" executed. In all speed measurements, you have to realize that it's always an average speed for a certain time period. The shorter the period, the more "current" the estimated speed is, but it'll also vary / jump around more.

As you can see, the code sample above doesn't take much CPU at all. But, you can of course put a "until" or "while" in where the "do stuff" is. THEN you should really include a Wait() to release CPU time, yes!

ricardocrl wrote: But this is a measure of the input "Speed" for the speed regulation mode, right? What it seems to me is that "MotorActualSpeed()" is like a voltage value, since it oscillates depending on the resistance you put in the outshaft of the motor. I would call it "MotorActualPower", since it's an oscillating value to keep a constant speed.
Yes, you're absolutely right, LEGO screwed up the name of that register a bit, MotorActualPower would make much more sense, as the number is a power value. It's not the input of the motor control, more like the effective output applied. It somehow reflects the output "power / voltage / PWM setting" the motor gets, yes.

Re: [NXC] How to get the real motor speed?

Posted: 08 Sep 2011, 19:39
by ricardocrl
Ok, nice! I see the constraints around getting the velocity. :-) It's a pity that the value is not shared by the FW, we have to deal with it.

Taking your "Wait()" suggestion, I would modify mattallen37 to the following:

Code: Select all

float MotorSpeed(byte port, unsigned int TimeFrame){
  unsigned long OriginalTime = CurrentTick();
  until (CurrentTick() >= OriginalTime + 2);
  long OriginalPosition = MotorTachoCount(port);
  if (TimeFrame > 2){
    Wait(TimeFrame - 2);
  }
  until (CurrentTick() >= OriginalTime + 2 + TimeFrame);
  long FinalPosition = MotorTachoCount(port);
  float Time = 60000 / TimeFrame;
  long PositionDifference = FinalPosition - OriginalPosition;
  return PositionDifference * Time / 360;                                       //FinalPositon minus OrigionalPosition is the distance turned.
                                                                                //360 is the number of positions the NXT motor changes per revolution.
                                                                                //TimeFrame/60000 is putting the TimeFrame in minutes.
}
The idea is to do a smaller Wait than the actual TimeFrame, due to possible jumps in the CPU times to other tasks, before the Wait command or after it. Note I haven't tried it...

Thank you both for the discussion! :-)

Re: [NXC] How to get the real motor speed?

Posted: 13 Sep 2011, 14:31
by mattallen37
I wouldn't do that. TimeFrame is supposed to be the window of time (in ms) that it uses to get a difference of values. It uses that difference of position, and the TimeFrame, to calculate the speed. TimeFrame is not supposed to be the total number of ms that it takes the function to return the value. If you want it to take less time to get the speed, then use a smaller number for TimeFrame.

Re: [NXC] How to get the real motor speed?

Posted: 15 Sep 2011, 01:00
by ricardocrl
But I'm not changing the meaning of TimeFrame. It is still the window time. The only difference is that, if TimeFrame is higher than 2, then, we can put the CPU doing other stuff during that time, instead of occupying some "1ms slices" using the CPU to calculate the statement:

Code: Select all

until (CurrentTick() >= OriginalTime + 2 + TimeFrame);
During that "wait time" that I'm adding, the CPU doesn't return to the thread running this function (if others exist).