07jkearney

Moving NXT Motors Simultaneously using NXC

Recommended Posts

I have recently begun programming in NXC, and while very useful, I cannot for the life of me figure out how to move two motors simultaneously (with different required movement angles). Below is the simplest way of doing this that I can come up with, can anyone suggest how to integrate this into my program? Or do you have an easier way of achieving the required actuation?

task Move_A()
{
RotateMotor(OUT_A, 30, 179);
}
task Move_C()
{
RotateMotor(OUT_C, 30, -179);
}
task main()
{
Precedes(Move_A,Move_C);
}

Also it would be great if the motors were synchronised, but this is not essential.

Share this post


Link to post
Share on other sites

I'm not sure if I understand your question correctly, but from what I see in your program you are trying to control both motors at the same time. I have made 2 simple programs for you. I will explain them more in detail.

task main ()
{
RotateMotor(OUT_BC, 75, 360);
RotateMotor(OUT_BC, 75, -360);
}

You had already found the 'RotateMotor' function, so I guess you know what it does. You're program might work, but it is not very efficient. You can declare 1 or 2 output motors in the function. As stated in the program, I control motor B and motor C at the same time. you could also use motor A and motor B or... It also works with only one motor for output of course.

RotateMotor(OUT_A, 75, 360)

Let's now move on to the same program with synched motors.

task main ()
{
RotateMotorEx(OUT_BC, 75, 360, 0, true, true);
RotateMotorEx(OUT_BC, 75, -360, 0, true, true);
}

Let me explain the different functions between brackets:

  • OUT_BC: defines the motors that you are using
  • 75 : motor speed (number between 0 & 100)
  • 360: degrees that you want to turn
  • 0: the difference between motors, but if you use a 2 wheeled robot, this should be set to 0. If you for example set this value to 50, one motor will turn 180 degrees and the other one 360.
  • 'true': tells the motors that they should be synced (basically this should always be set to 'true')
  • 'true': tells the motors to stop at the end of the program. If set to 'false' the motors will not stop at the same time. You should always set this to 'true' to have a accurate robot.

I hope this helped you out. And I hope my explanation is understandable.

If you have more questions, just ask :)

Edited by Ramacco

Share this post


Link to post
Share on other sites

Many thanks for your excellent reply, unfortunately I have already researched and attempted to use the 'RotateMotorEx' function, and, while useful for a typical two wheeled robot it is not suitable for what I have in mind to the best of my knowledge;

I cannot for the life of me figure out how to move two motors simultaneously (with different required movement angles).

Share this post


Link to post
Share on other sites

What I was trying to do was move two different motors, at different speeds, through different angles, simultaneously.

Thanks for trying to help though :classic:

P.s. That tutorial was how I leaned to program :grin:

Share this post


Link to post
Share on other sites

What I was trying to do was move two different motors, at different speeds, through different angles, simultaneously.

The first example Ramacco gives is not suitable for your needs? Seems exactly what you need to me.

Share this post


Link to post
Share on other sites

Unfortunately I would need a separate 'RotateMotor' function for each motor (because they need to turn different distances) and the second rotate motor command would wait for the first one to finish executing :sceptic:

I am currently redesigning the hardware to avoid this issue.

Share this post


Link to post
Share on other sites

I now understand what you mean. Doesn't NXC have the option to continue without waiting?

You could write a PID controller to avoid this issue, but that will need some experience.

You shouldn't use a fixed rotation, but adjust the power level and check the rotation on a regular basis. Then stop the motor when the destination angle has been reached. In a nutshell.

Share this post


Link to post
Share on other sites

Read this article about PID. It's a very clear and understandable read. You just need to translate it to your needs.

http://www.inpharmix.com/jps/PID_Controller_For_Lego_Mindstorms_Robots.html

I have no idea what you are trying to do, but it seems that a subroutine is a valid option if both motors have to run at the same time.

You might consider reading this: http://bricxcc.sourc...XC_tutorial.pdf

Page 34 of this tutorial also mentions PID control.

But I still guess NXC should be able to continue after a motor command.

Share this post


Link to post
Share on other sites

Just tried using PID, but the program quickly became overly complex, and I can't get it to work properly :hmpf_bad:

How hard can it be to translate the attached NXT-G code into NXC?! Everything I've tried has failed.

post-30449-0-25818100-1380561015_thumb.jpg

Share this post


Link to post
Share on other sites

Just to be clear. This doesn't work?

RotateMotor(OUT_A, 100, 360)

RotateMotor(OUT_B, -50, 180)

Share this post


Link to post
Share on other sites

Just to be clear. This doesn't work?

RotateMotor(OUT_A, 100, 360)

RotateMotor(OUT_B, -50, 180)

I think the issue with the above code is that the first line has to execute first, and then when completely done, the second line begins to execute. What this means is that one motor spins first, and only when it is finished the second motor start to turn. What the OP is asking for is how to run the two motors at the SAME time, not one after the other. My take is that this is a classical issue/limitation with most 'sequential' type programming. One fix would be to issue the above commands several times, and divide the respective motions into as many increments, but this would yield to non-smooth operation of the motors. The way I would do this (assuming such functions exist) is to start the motors and continuously check if they reached target positions/angles:

while (1)

{ start rotating motor A

start rotating moror B

if both motors have reached final position, exit loop

}

Share this post


Link to post
Share on other sites

True! I just found out this is indeed the case.

You could create separate threads.

Or like you said:

"The way I would do this (assuming such functions exist) is to start the motors and continuously check if they reached target positions/angles:"

That was my idea as well. But this might be inaccurate. Maybe use PID controllers for both motors, but things will get pretty complicated for an easy function.

  1. Set power motor A
  2. Set power motor B
  3. Check continuously to see whether conditions have been met

I am told that Lejos does this better.

Quote:

In lejos you can rotate 2 motors simultaneously with a different angle. You can use something like Motor.A.controlMotor(speed, forward); (however, the motors will rotate forever, but you can see the difference if you put one in backward and the other motor in forward).

You may want to look here :

http://www.lejos.org.../nxt/Motor.html

Share this post


Link to post
Share on other sites

Funny that such a simple action cannot be achieved simply in NXC, I think I'm going to concede defeat and use another solution. Thanks for the help anyway guys :thumbup:

Share this post


Link to post
Share on other sites

Good post. Another option to manage simultaneous motion of both motors is by use of 'interrupts' ... though not sure such functions exist in either NXC or Lejos.

Essentially what we need are two SEPARATE functions: one to start the motor, and the other to stop it. If those are somehow available, then the OP's puzzle can be solved by either nested loops and/or IF/AND statements. From what I have seen, most 3rd party codes have a single function to operate a motor, with predefined speed/angle.

I wonder, is this possible:

Start Motor 1 (slow speed, infinite number of rotations)

while above is running, Start Motor 2 (again, slow speed, infinite number of rotations)

if (angle 1 reached) or (angle 2 reached) stop both motors

if (angle 1 not reached), move/restart motor 1 to desired angle.

if (angle 2 not reached), move/restart motor 2 to desired angle.

The issue above is that, even if we can start motors at the same time, we do need as well to STOP them separately (two parallel IF statement). This is typically not how IF statements work (not in parallel)... Hence (in above code) the need to stop both motors if EITHER reaches target position, then restart the one lagging. Sounds complicated ...

Funny that such a simple action cannot be achieved simply in NXC, I think I'm going to concede defeat and use another solution. Thanks for the help anyway guys :thumbup:

Wait, this is an interesting programming puzzle ... I'm curious to see a solution as well.

Edited by DrJB

Share this post


Link to post
Share on other sites

You need 2 tasks, task one for motor a and task 2 for motor b, they can then do what you want at the same time

Which you have, so I wonder why it does not work for you

Share this post


Link to post
Share on other sites

It does work, but is difficult to integrate into a full program, I was wondering if their was a more concise way of achieving the same thing.

Share this post


Link to post
Share on other sites

Hmm, i sued the same idea to create a robot arm that could move through a smooth arc. it works fine, but you have to keep checking your targets. In my case i was using inverse kinematics to calculate the angels needed to move the end effector (pen in my case) to where it needed to be, then i took the ratio of the 2 angles needed and sued that to set the power of the 2 outputs (within limits) and then set it off, in this way they both got to there end point at the same time in a single continues movement. I was aiming for a resolution or around 1mm so each step was small, hence each task would rune quickly.

Share this post


Link to post
Share on other sites

Hmm, i sued the same idea to create a robot arm that could move through a smooth arc. it works fine, but you have to keep checking your targets. In my case i was using inverse kinematics to calculate the angels needed to move the end effector (pen in my case) to where it needed to be, then i took the ratio of the 2 angles needed and sued that to set the power of the 2 outputs (within limits) and then set it off, in this way they both got to there end point at the same time in a single continues movement. I was aiming for a resolution or around 1mm so each step was small, hence each task would rune quickly.

I am using the same technique for the head of my robot. It rotates, tilts and the eyes move (wall-e style). So when the head rotates you need to compensate for the tilt etc.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.