NXC - motors synchronization

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
psorek
Posts: 13
Joined: 12 Feb 2012, 07:50

NXC - motors synchronization

Post by psorek »

I need to turn motor OUT_A and OUT_B parallelly. Every motor has previously defined degree (signed) what i want to turn. The move must start and end in the same moment for these motors. How can i do it?

I thought about function RotateMotorEx (), but i dont understand how to use it like i wanted.

i have two variables which are needed to do it.
int x; // degree for OUT_A
int y; // degree for OUT_B


sorry about my english, i have problems with vocabulary conected with robots :)
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: NXC - motors synchronization

Post by HaWe »

that's not precisely possible by NXC for any combination of target values: The synch mode is rather odd.
You only can roughly do this if you choose PWM-power in relation to the number of degrees to go.
You may choose independend PWM values for 2 independend motor control functions (1 specific call for each single motor).
So because you don't need a sync mode for just 1 motor, you may better use

Code: Select all

void RotateMotor  ( byte  outputs,  char  pwr,  long  angle )

instead of RotateMotorEx .

E.g. if A has to run 3000 degrees and B has to run 4000 degrees then you could choose pwrA=60 and pwrB=80
Start both in independend RotateMotor calls:

Code: Select all

RotateMotor(OUT_A, 60, 3000);
RotateMotor(OUT_B, 80, 4000);
HTH!
psorek
Posts: 13
Joined: 12 Feb 2012, 07:50

Re: NXC - motors synchronization

Post by psorek »

I am at 90% sure that RotateMotor function waits until rotation is done. It can be a problem -.-
Maybye 2 tasks with RotateMotor running paralelly?
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: NXC - motors synchronization

Post by HaWe »

yes, of course, if required!
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

Re: NXC - motors synchronization

Post by mattallen37 »

If I needed precise control of keeping two motors closely in sync, I would try using a custom P or PD controller for the differential (and add and subtract that value to and from the two motor speeds).
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
psorek
Posts: 13
Joined: 12 Feb 2012, 07:50

Re: NXC - motors synchronization

Post by psorek »

precision is needed, because it will be a ploter.

How works RotateMotor? Does it wait until rotating is ended?

How to write this parallelly turning with tasks? Please, write an example for me :)

Code: Select all

int Mox, Moy, a;
mutex Mx, My;

task MoveX()
{
     Acquire (Mx);
     RotateMotor (OUT_B, (50*Mox)/a, abs(Mox));
     Release (Mx);
}

task MoveY()
{
     Acquire (My);
     RotateMotor (OUT_A, (50*Moy)/a, abs(Moy));
     Release (My);
}

void PenMove (int x, int y)
{
     PenPosx+=x;
     PenPosy+=y;
     x*=Cx;
     y*=Cy;
     a=max(x, -x);
     int b=max(y, -y);
     a=max(a, b);
     Precedes (MoveX, MoveY);
     Wait (100);
     Acquire (Mx);
     Release (Mx);
     Acquire (My);
     Release (My);
}
why it doesn't work (dsnt compile)
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

Re: NXC - motors synchronization

Post by mattallen37 »

psorek wrote:why it doesn't work (dsnt compile)
You need a main task, so the program knows where to start.
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: NXC - motors synchronization

Post by afanofosc »

Do you have any thoughts as to why the code you posted might not compile? What do the error messages and their line numbers tell you?

One thing for sure is every NXC program requires a task called "main" which you don't have in what you posted. That's one problem. There are many others from what I can see.

Here's an example of how to start two tasks that each rotate a single motor:

Code: Select all

int power_a;
int angle_a;
int power_b;
int angle_b;

task moveA()
{
  RotateMotor(OUT_A, power_a, angle_a);
}

task moveB()
{
  RotateMotor(OUT_B, power_b, angle_b);
}

task waitForAB()
{
  Follows(moveA, moveB);
  // do something once both have reached their destination
  PlayTone(TONE_A4, SEC_5);
  ExitTo(startMovingAB);
}

task startMovingAB()
{
  Precedes(moveA, moveB);
  // calculate the correct values for power_a, power_b, angle_a, and angle_b
  power_a = 40+Random(50);
  power_b = 40+Random(50);
  angle_a = 180+Random(3600)*sign(Random()); 
  angle_b = 180+Random(3600)*sign(Random());
}

task main()
{
  Precedes(startMovingAB);
}
The above code is completely untested and may not even compile.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
psorek
Posts: 13
Joined: 12 Feb 2012, 07:50

Re: NXC - motors synchronization

Post by psorek »

It was only part of code. I have to read about "Follows" function. I think so i know why it didn't work.
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: NXC - motors synchronization

Post by afanofosc »

I have tried out the code I posted and with a couple minor changes it works great. You might consider using something like this approach for your plotter.

Code: Select all

int power_a;
int angle_a;
int power_b;
int angle_b;

task moveA()
{
  RotateMotor(OUT_A, power_a, angle_a);
}

task moveB()
{
  RotateMotor(OUT_B, power_b, angle_b);
}

task startMovingAB()
{
  Precedes(moveA, moveB);
  // calculate the correct values for power_a, power_b, angle_a, and angle_b
  power_a = 40+Random(50);
  power_b = 40+Random(50);
  angle_a = 180+Random(3600)*sign(Random());
  angle_b = 180+Random(3600)*sign(Random());
}

task waitForAB()
{
  Follows(moveA, moveB);
  // do something once both have reached their destination
  PlayTone(TONE_A4, MS_500);
  Wait(SEC_1);
  ExitTo(startMovingAB);
}

task main()
{
  Precedes(startMovingAB);
}
This program will randomly move A and B simultaneously at random power levels. Once both motors have reached their target the waitForAB task will start running and at the end of that task it starts up the startMovingAB task again which will choose new power levels and angle targets for OUT_A and OUT_B before scheduling the two motor movement tasks to run simultaneously again.

The RotateMotor API function calls Acquire and Release internally so there is no reason to explicitly acquire a mutex outside these function calls. Precedes and Follows are task scheduling directives rather than API commands, per se. They tell the compiler to configure the RXE executable so that the firmware's task scheduler will correctly schedule tasks to execute. The directives can be placed anywhere within a task or subroutine but they do not execute any code at runtime so their position within a routine is arbitrary. I recommend putting them at the start of the routine. If you tell the compiler that a task follows multiple other tasks then it will not execute until all of the tasks it follows have finished executing. This is a data-flow programming paradigm. All the required inputs to a routine must be available before the routine will begin to execute. The ExitTo routine allows you to at runtime tell the task scheduler to exit the current routine and schedule the specified routine to begin execution.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
Post Reply

Who is online

Users browsing this forum: No registered users and 32 guests