[NXC] How to get the real motor speed?

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
Post Reply
ricardocrl
Posts: 117
Joined: 27 Dec 2010, 19:27

[NXC] How to get the real motor speed?

Post 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
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

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

Post 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);
  }
}
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
ricardocrl
Posts: 117
Joined: 27 Dec 2010, 19:27

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

Post 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?
linusa
Posts: 228
Joined: 16 Oct 2010, 11:44
Location: Aachen, Germany
Contact:

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

Post 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
RWTH - Mindstorms NXT Toolbox for MATLAB
state of the art in nxt remote control programming
http://www.mindstorms.rwth-aachen.de
MotorControl now also in Python, .net, and Mathematica
ricardocrl
Posts: 117
Joined: 27 Dec 2010, 19:27

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

Post 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.
linusa
Posts: 228
Joined: 16 Oct 2010, 11:44
Location: Aachen, Germany
Contact:

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

Post 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.
RWTH - Mindstorms NXT Toolbox for MATLAB
state of the art in nxt remote control programming
http://www.mindstorms.rwth-aachen.de
MotorControl now also in Python, .net, and Mathematica
ricardocrl
Posts: 117
Joined: 27 Dec 2010, 19:27

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

Post 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! :-)
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

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

Post 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.
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
ricardocrl
Posts: 117
Joined: 27 Dec 2010, 19:27

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

Post 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).
Post Reply

Who is online

Users browsing this forum: No registered users and 3 guests