07jkearney Posted September 28, 2013 Posted September 28, 2013 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. Quote
Ramacco Posted September 28, 2013 Posted September 28, 2013 (edited) 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 September 28, 2013 by Ramacco Quote
07jkearney Posted September 28, 2013 Author Posted September 28, 2013 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). Quote
Ramacco Posted September 28, 2013 Posted September 28, 2013 (edited) 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 Or look at the mindboards forum for more people to help you. Edited September 28, 2013 by Ramacco Quote
07jkearney Posted September 28, 2013 Author Posted September 28, 2013 What I was trying to do was move two different motors, at different speeds, through different angles, simultaneously. Thanks for trying to help though P.s. That tutorial was how I leaned to program Quote
Jim Posted September 29, 2013 Posted September 29, 2013 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. Quote
07jkearney Posted September 30, 2013 Author Posted September 30, 2013 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 I am currently redesigning the hardware to avoid this issue. Quote
Jim Posted September 30, 2013 Posted September 30, 2013 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. Quote
07jkearney Posted September 30, 2013 Author Posted September 30, 2013 Nice idea Jim , I'll see what I can come up with. Quote
Jim Posted September 30, 2013 Posted September 30, 2013 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. Quote
07jkearney Posted September 30, 2013 Author Posted September 30, 2013 Just tried using PID, but the program quickly became overly complex, and I can't get it to work properly How hard can it be to translate the attached NXT-G code into NXC?! Everything I've tried has failed. Quote
Jim Posted October 2, 2013 Posted October 2, 2013 Just to be clear. This doesn't work? RotateMotor(OUT_A, 100, 360) RotateMotor(OUT_B, -50, 180) Quote
DrJB Posted October 2, 2013 Posted October 2, 2013 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 } Quote
Jim Posted October 2, 2013 Posted October 2, 2013 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. Set power motor A Set power motor B 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 Quote
07jkearney Posted October 2, 2013 Author Posted October 2, 2013 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 Quote
DrJB Posted October 2, 2013 Posted October 2, 2013 (edited) 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 Wait, this is an interesting programming puzzle ... I'm curious to see a solution as well. Edited October 2, 2013 by DrJB Quote
07jkearney Posted October 2, 2013 Author Posted October 2, 2013 It drives me insane that it's so simple in NXT-G, all my equivalent NXC programs are ridiculously complex Quote
kieran Posted October 3, 2013 Posted October 3, 2013 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 Quote
07jkearney Posted October 3, 2013 Author Posted October 3, 2013 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. Quote
kieran Posted October 4, 2013 Posted October 4, 2013 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. Quote
Jim Posted October 4, 2013 Posted October 4, 2013 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. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.