View unanswered posts | View active topics It is currently Thu Nov 27, 2014 1:54 pm






Reply to topic  [ 11 posts ] 
Syncing motors in whait until push 
Author Message
Rookie

Joined: Sun Mar 04, 2007 3:02 am
Posts: 9
Post Syncing motors in whait until push
I am trying to add motor syncronization to the wait until push sample program but the robot turns instead of going straight. What's wrong?

Code:
   nSyncedMotors      = synchBC;  // "C" will be synchronized to "B".
   nSyncedTurnRatio   = 100;
   nPidUpdateInterval = 10; 
   while(SensorValue(touchSensor) == 0)   
   {
      motor[motorB] = 40;             
   }


This turns , it doesn't go straight. Why is that?

Bill


Thu Mar 08, 2007 3:31 pm
Profile
Creator
Creator

Joined: Fri Feb 09, 2007 9:21 am
Posts: 615
Post 
Make sure that your motors are connected to B and C and not to A. [I know, its obvious, but sometimes people forget].

Try the following code. Post a message if it works or not.

Code:

Code:
nSyncedMotors      = synchBC;  // "C" will be synchronized to "B".
   nSyncedTurnRatio   = 100;
   nPidUpdateInterval = 10; 
   motor[motorB] = 40;
   while(SensorValue(touchSensor) == 0)   
   {
      wait1Msec(1);           
   } 

The change is that the motor speed setting is moved outside of the loop. When it was inside the loop it was continually "re-initializing" the synchronization so that it didn't have a chance to work well.

NOTE: A future version will not perform the reset if the speed is the same as the current settings.


Thu Mar 08, 2007 10:07 pm
Profile
Novice

Joined: Sun Feb 04, 2007 12:48 am
Posts: 69
Location: Australia
Post 
I'm trying to do a swing turn in a program where the two driving motors A & B have been synchronised together with A being declared kPrimaryMotor.

The following code works fine when I'm doing a swing turn where only motor A is used. However when I'm doing a swing turn in the opposite direction using only the slave motor (motorB) it throws an exception error. If I'm using the debugger window I can ignore it and continue but it appears that the EncoderTarget setting on motorB doesn't stop the motor anyway.

Code:
       nSyncedTurnRatio         = 0;  //Turn ratio stopped
       nMotorEncoder[motorB]=0;
       nMotorEncoderTarget[motorB] = nNoOfRotationsST;
       motor[motorB] = 60;
       while (nMotorRunState[motorB] != runStateIdle)
            {      //Wait till finished
            }


Issues/Questions:
1) When two motors are synch'd, are you not allowed to send instructions/control the slave motor or its encoder, am I doing something wrong or is it a bug?
2) I initially had the constant declarations (listed below) inside the various functions but it seemed to throw exceptions because I was trying to reset a constant each time the function was called after the first time.
Code:
const TSynchedMotors kSyncType     = synchAB;
const tMotor         kPrimaryMotor = motorL;

So I listed these globally which resolved the problem. Was this a good idea? In the context of the question above, how do you switch synching of motors on and off if you are jumping between Swing and Point turns?

Thanks
James


Sun Apr 29, 2007 8:14 am
Profile
Creator
Creator

Joined: Fri Feb 09, 2007 9:21 am
Posts: 615
Post 
You need to use "synchAB" when turning to the B side.

When turning to the "A" side, you need to use "synchBA" as "B" will be the primary motor.

This is not the most elegant interface and I'm looking for a way to make it a bit easier to use.


Sun May 06, 2007 10:22 pm
Profile
Rookie

Joined: Sun Apr 15, 2007 8:33 am
Posts: 40
Location: USA
Post 
Hello,
A nice ZTR ...

Add these functions to your code then update the global constants used by geometrical functions (be very precize, size is expressed in centimeter).

I assume that motors are B & C...

Then from your main code call :

for a 360 Zero Turn Radius...

1) EncoderTicks is computing the number of encoder ticks based on the input rotation angle.
2) call ZTRmotion with motorPower=3, motorDegree and the Direction..

MotorDegrees = EncoderTicks(360,(float)RobotDiameter);
SavedMotorEncoder1 = ZTRmotion(3,MotorDegrees,TurnRight);

Obviously you can set the motor power based on your need...

If the turn is to large because of the kinetic force then the function should automatically adjust the position... Enjoy!

//* ********************************************************** *
//* *
//* ********************************************************** *
const int TurnLeft = -1;
const int TurnRight = 1;
//* ********************************************************** *
//* * Global variables used for odometer and geometrical functions
//* ********************************************************** *
const float WheelDiameter = 8.16; // in centimeters(cm) - Wheel diameter
const float DistancePerDegree = 0.071; // in centimeters(cm) - (WheelDiameter*PI)/360
const float RobotDiameter = 5.70; // in centimeters(cm) - robot diameter from L-center wheel to R-center wheel
//* ********************************************************** *
//* *
//* ********************************************************** *
int EncoderTicks(int deg,float RadiusTurn)
{
float CirconferenceWheel = 0.0;
float CirconferenceTurn = 0.0;
float DistanceTraveledByTheWheel = 0.0;
float Coef = 0.0;
int MotorDegrees = 0;
CirconferenceWheel = PI * WheelDiameter;
CirconferenceTurn = PI * (RadiusTurn * 2.0);
DistanceTraveledByTheWheel = CirconferenceTurn * ((float) deg / 360.0);
Coef = DistanceTraveledByTheWheel / CirconferenceWheel;
MotorDegrees = (int)(360.0 * Coef);
return(MotorDegrees);
}
//* ********************************************************** *
//* *
//* ********************************************************** *
int ZTRmotion(int nPower,int nEncoder,int nMotion)
{
int nSavedMotorEncoder = 0;
int nDelta = 0;
nSchedulePriority = kDefaultTaskPriority;
bFloatDuringInactiveMotorPWM = false;
nMaxRegulatedSpeed = 3600;
nPidUpdateInterval = 1;
nMotorPIDSpeedCtrl[motorB] = mtrEncoderReg;
nMotorPIDSpeedCtrl[motorC] = mtrEncoderReg;
nSyncedMotors = synchBC;
nSyncedTurnRatio = -100;
nMotorEncoder[motorB] = 0;
nMotorEncoderTarget[motorB] = 0;
motor[motorB] = nPower * nMotion;
while(true)
{
if (abs(nMotorEncoder[motorB])== nEncoder)
{
motor[motorB] = 0;
break;
}
}
while(nMotorRunState[motorB] != runStateIdle);
wait1Msec(300);

nSavedMotorEncoder = abs(nMotorEncoder[motorB]);

if (nEncoder < abs(nMotorEncoder[motorB]))
{
bFloatDuringInactiveMotorPWM = false;
nMaxRegulatedSpeed = 3600;
nPidUpdateInterval = 1;
nMotorPIDSpeedCtrl[motorB] = mtrEncoderReg;
nMotorPIDSpeedCtrl[motorC] = mtrEncoderReg;
nSyncedMotors = synchBC;
nSyncedTurnRatio = -100;
nMotorEncoder[motorB] = 0;
nMotorEncoderTarget[motorB] = 0;
nDelta = nSavedMotorEncoder - nEncoder;
nMotorEncoderTarget[motorB] = nDelta;
if (nMotion == 1) motor[motorB] = 2 * -1;
if (nMotion == -1) motor[motorB] = 2 * 1;
while(nMotorRunState[motorB] != runStateHoldPosition){wait1Msec(1);};
wait1Msec(300);
}
bFloatDuringInactiveMotorPWM = false;
nSyncedMotors = synchNone;
return(nEncoder);
}

_________________
SuntzuMaster- a French gentlemen in USA.


Mon May 07, 2007 8:49 am
Profile
Rookie

Joined: Sun Apr 15, 2007 8:33 am
Posts: 40
Location: USA
Post 
Small update...

the "RobotDiameter" must be interpreted as RobotRadius...

I shall change the name for this variable in my current program!

have a good day.

jm

_________________
SuntzuMaster- a French gentlemen in USA.


Mon May 07, 2007 6:27 pm
Profile
Rookie

Joined: Sun Apr 15, 2007 8:33 am
Posts: 40
Location: USA
Post 
For a best motor(s) control one should use "EncoderClosedLoop".
Should be setup using the wizard...

jm.

_________________
SuntzuMaster- a French gentlemen in USA.


Mon May 07, 2007 6:34 pm
Profile
Novice

Joined: Sun Feb 04, 2007 12:48 am
Posts: 69
Location: Australia
Post 
Well I've experimented with your code and got it to work well. Actually one of my students had been writing a similar program but it was a little clunky and lacked some of your finesse.

I do have a few queries.

1) You repeat the following code twice in the ZTRmotion function.
Quote:
bFloatDuringInactiveMotorPWM = false;
nMaxRegulatedSpeed = 3600;
nPidUpdateInterval = 1;
nMotorPIDSpeedCtrl[motorL] = mtrEncoderReg;
nMotorPIDSpeedCtrl[motorR] = mtrEncoderReg;
nSyncedMotors = synchAB;
nSyncedTurnRatio = -100;

Is this neccessary? Or is it a good protocol?

2) I notice you often use the statement
Quote:
nSchedulePriority = kDefaultTaskPriority;
in your programs is this just a good protocol to follow for more elaborate programs?

3) Why do you put
Quote:
nMaxRegulatedSpeed = 3600;
in? Why is it necessary & what does it do/prevent? Once again is it just a good habit?

4) I like your overshoot correction solution as it works well. However I was surprised to find it was necessary. I thought I read somewhere that RobotC used a very good PID controller to prevent overshoot when using the encoders even under load.

Please note, I'm not trying to be critical I'm just trying to learn.

Thanks
James


Last edited by JamesD on Thu May 10, 2007 8:11 pm, edited 1 time in total.



Thu May 10, 2007 8:25 am
Profile
Rookie

Joined: Sun Apr 15, 2007 8:33 am
Posts: 40
Location: USA
Post 
Hi James,

1) I like to be in control of my code... that is why sometime I repeat some chunck of code... I think that it is not mandatory to repeat it...
However, you have to know that I have been playing with NXT & ROBOTC for less than 3/4 weeks now, I am still a beginner here.
That is why my code is not as optimized as it could be.

2) I set the priority each time when I start a task or even when I call a function because I like the fact that when I deal with a multitasking program I can remember that the O/S scheduler could play awoke in term of how the events are comming and on how the arbiter should be designed.

3) By experience I would like to say that I do not trust "compiler or firmware defaults setup"... because they can change or let's say be changed without warning...

4) Yes there are a DIP imbedded inside the NXT motors but based on the benchmark I ran they do not do a job good enough... faster the motor spin bigger the kinetic energy is... then even if you specify a number of encoder clicks with mtrEncoderReg you will never at the best of my current understanding stop at the exact location that you want to stop at!

I saw the video that Dick Swan sent me the links and I think that there are things like: track size, steerring control, ... turn angle(s)... I think that tracks shape is important in term of how the robot program is designed... I shall put more thought on that specific item.

more questions let me know!

have a great day!

_________________
SuntzuMaster- a French gentlemen in USA.


Thu May 10, 2007 12:49 pm
Profile
Rookie

Joined: Sun Apr 15, 2007 8:33 am
Posts: 40
Location: USA
Post 
I am at my office I shall give you more explanation about the parameters settings when I ll go home today.

bye.

_________________
SuntzuMaster- a French gentlemen in USA.


Thu May 10, 2007 12:53 pm
Profile
Rookie

Joined: Sun Apr 15, 2007 8:33 am
Posts: 40
Location: USA
Post 
I also repeat the code because the ZTR... function can be called from anywhere in your program then I cannot assume that the motor(s) setup is the one that I want to use with the ZTRmotion function.
Then it is good pratice to design a function with all the required setup embedded inside, with that in mind you can build a shared functions library.

You can then build programs more quickly with functions that you know have been already tested.

_________________
SuntzuMaster- a French gentlemen in USA.


Thu May 10, 2007 2:46 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 11 posts ] 

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.