Crossing zero in a 360 rotary actuator curve.

I’ve been getting an extra full 360 rotation when my curve crosses zero.

For example the curve points are something like 358.0 and the next point is 0.0 and the unit will do a full 360 rather then do just the 2 psu.

Of course I get tracking errors and such and then it will catch back up to next point in the curve.

I’m using a reference axis to control speed of the curve and its just a regular linear ramp.

Do I have to use an rotary reference axis to get it play through?

Thanks,

Chuck

I think that in order to get it to go from 358 to 0 without doing an almost-full 360, the curve points need to be 358 and 360, not 358 and 0. I am not sure exactly what kind of curve you have or what the machine needs to do, but if you are repeating the curve endlessly, it should still work to have the first point be zero and the last point be 360. You may need to set the curve options and Curve Start Advanced command options correctly to get it to work.

I don’t think changing the reference axis would make any difference.

This axis is a rotary servo with a 14 bit SSI encoder. I’m controlling by playing a curve generated by 3D data derived from a cad model. The curve has a max/min value of 360 to 0 degrees. There is both sinusoidal parts of the curve and multi-rotational parts. The time base is also devised from another model and is not linear.

For example: The first portion of the curve has the sinusoidal like movement, about the zero degree mark, the second portion has rotations in one direction. So the rotary axis should go back and forth 30 times then start going around there after. See supplied Tab file. I’ve been running it linear.

I’ve tried replacing the zero’s with 360’s, No Luck.
Iv’e tried just using just an 88 from the command bar to play the curve (no master axis), No Luck.

I would assume if I could do a move absolute with the nearest direction option it play, but it’s a curve and I’m at a loss to get it to a nearest point to point and make that 358 to 0 leap with just 2 PU movement.

Any help would be appreciated,

Thanks,

Chuck

Hi Chuck,

Can you send your project file to support@deltamotion.com. Also include a curve file that is causing problems. If you have a plot of the resulting motion that would be great as well. (I didn’t see an attached file to your last post.)

With the project file I will be able to see exactly how the axis is configured, and with the curve file I will be able to see the exact sequence of points you are using. With that I hope to be able to determine what needs to happen to get the behavior you want.

Thanks,

David Shroyer

Hi David,

Sent an email with the project file.

I have a function to detect crossing a point around a circle. It returns 0 if the point isn’t crossed. It returns 1 the point is crossed in the positive direction and -1 if the point is crossed in the negative direction.

David wrote me back and said:

The problem with the curves is that they are already wrapped. When you create the curve you need to make them continuous. The points can go outside the 0 to 360 range of the rotary axis. For example:
Instead of entering the following sequence of points:
355
356
357
358
359
0
1
2
3
You need to enter the points as:
355
356
357
358
359
360
361
362
363
364

The controller will take care of the unwinding of the values outside the axis range. This is necessary because we don’t have a mechanism to specify that the curve should be followed through the nearest direction.

Given this,
I had to rotate my curve by 90 degrees to move the center of the cyclic motion away from zero degree center and when it goes to the rotational part, I made the points add to each rotation as he has suggested and it works fine now!

Copy and paste this into the User Functions. Call this from the link condition

(*
	ROTATIONAL LIMIT SWITCH
	IF CROSSING LS IN THE POSTIVE DIRECTION, RETURNS 1
	IF NOT CROSSING LS, RETURNS 0
	IF CROSSING LS IN THE NEGATIVE DIRECTION, RETURNS -1
*)

FUNCTION ROT_LS : DINT
	VAR_INPUT
		NEW_POS: REAL;	// NEW POSITION
		LS_POS: REAL;		// LIMIT SWITCH POSITION TO BE DETECTED
		CIRCUM: REAL;		// CIRCUMFRENCE,  USUALLY POSITION UNWIND
	END_VAR
	VAR_IN_OUT
		OLD_POS: REAL;	// THE OLD POSITION
	END_VAR
	VAR
		DIF0: REAL;
		DIF1: REAL;
		DIF2: REAL;
		HALF_WAY: REAL;
	END_VAR

	HALF_WAY:=0.5*CIRCUM;
	DIF0:=NEW_POS-LS_POS;
	IF DIF0> HALF_WAY THEN
		DIF0:=DIF0-CIRCUM;
	ELSEIF DIF0 < -HALF_WAY THEN
		DIF0:=DIF0+CIRCUM;
	END_IF
	DIF1:=OLD_POS-LS_POS;
	IF DIF1> HALF_WAY THEN
		DIF1:=DIF1-CIRCUM;
	ELSEIF DIF0 < -HALF_WAY THEN
		DIF1:=DIF1+CIRCUM;
	END_IF
	DIF2:=NEW_POS-OLD_POS;
	OLD_POS:=NEW_POS;
	IF DIF2> HALF_WAY THEN
		DIF2:=DIF2-CIRCUM;
	ELSEIF DIF2 < -HALF_WAY THEN
		DIF2:=DIF2+CIRCUM;
	END_IF
	IF DIF2 > 0.0 THEN
		IF DIF0 >= 0.0 AND DIF1 <0.0 THEN
			ROT_LS:=1;
		ELSE
			ROT_LS:=0;
		END_IF
	ELSE
		IF DIF0 <= 0.0 AND DIF1 >0.0 THEN
			ROT_LS:=-1;
		ELSE
			ROT_LS:=0;
		END_IF
	END_IF

END_FUNCTION

I’m not sure how to implement this function when playing back a curve with multiple zero crossings, will you please explain further?

Thanks,

Chuck

Chuck, I am assuming that rotating actuator is rotating back and forth through 0. There are two ways to use the ROT_LS function but they both have one thing in common. The ROT_LS function must be called whenever it is possible to cross the limit switch or zero position in your case. The two ways are to:
1: Use the ROT_LS function in the program triggers.

In this case I would use two calls to ROT_LS. One line would look like this

ROT_LS(_AXIS[0].TarPos,0,360,LastPos)=1
and the other would look like this
ROT_LS(_AXIS[0].TarPos,0,360,LastPos)=-1
To the right I would specify the program that needs to be execute when the result is 1 or -1.

2: Use a separate task for monitoring the rotation. I think this is the best way and more efficient.

If you have a spare task available I would use a spare task where ROT_LS is called every scan in a tight loop. like this:

LS:=ROT_LS(_AXIS[0].TarPos,0,360,LastPos);

Then you can do what you need to do when LS is set to 1 or -1
IF LS=1 THEN
// PUT THE CODE YOU NEED TO EXECUTE HERE.
END_IF
IF LS=-1 THEN
// PUT THE CODE YOU NEED TO EXECUTE HERE.
END_IF

If I simply wanted to count rotations I would write this:

ROTATIONS := ROTATIONS+LS; // LS CAN BE -1,0 OR 1

Chuck, it would be best if you would describe what you want to do at each zero crossing.

Hi Peter,

Thanks for the reply, I think I can use this IF I step up to the 150. I’m maxed out task wise at present on the 75.

Included is the curve file. Please rename extension back to *.rmccrvs. (The attachment app does not like it.)

This is the file that started all this. The two files are played back simultaneously. a1_29_H is heading (0-360 deg) and a1_27_P is pitch (0-180 deg). Think of a chain gun under the nose of an Apache helicopter and you get the idea of the movements except this one squirts water and can go round and around as well as back and forth.

Presently when I’m doing rotational stuff like this I add the rotations together and let the rmc unwrap them. It adds more steps in the compiling but now I understand why it needs it. It also makes it harder to visualize the rotation curves, now there just squiggly stair step affairs.
zero_crossing_curve.txt (778 KB)