SPINDLE SERVO SPECS

Moderators: TomKerekes, dynomotion

turbothis
Posts: 165
Joined: Fri Mar 15, 2019 4:07 pm
Location: southern oregon

SPINDLE SERVO SPECS

Post by turbothis » Wed Apr 03, 2019 3:44 pm

SO TRYING TO FIGURE OUT SOME SPINDLE SPECS FOR TOP SPEED (RPM)
i got 8192 count servo
servo drives a large pulley at 0.69 ratio
so 11872.46 counts per revolution
i would like to limit lathe spindle to 1500 rpm

so in the C program the Velocity number would be reading just encoder count right? per second or something?
so 1500 rpm is 25 per second
so 25 x 11872.46 is 296811 velocity?

Moray
Posts: 191
Joined: Thu Apr 26, 2018 10:16 pm

Re: SPINDLE SERVO SPECS

Post by Moray » Wed Apr 03, 2019 3:50 pm

That figure looks good to me, although you want to try and keep as much accuracy as possible and not round the number - 296811.5942028985507246

turbothis
Posts: 165
Joined: Fri Mar 15, 2019 4:07 pm
Location: southern oregon

Re: SPINDLE SERVO SPECS

Post by turbothis » Wed Apr 03, 2019 3:58 pm

my calculator just saidxxxxx.59 lol

User avatar
TomKerekes
Posts: 986
Joined: Mon Dec 04, 2017 1:49 am

Re: SPINDLE SERVO SPECS

Post by TomKerekes » Wed Apr 03, 2019 4:29 pm

Hi turbothis,

Normally speed is limited by simply limiting what the Spindle can be commanded to do.

What are you trying to do? Allow a higher speed to be commanded, then detect when the speed is actually too high, then kill it?
Regards,

Tom Kerekes
Dynomotion, Inc.

turbothis
Posts: 165
Joined: Fri Mar 15, 2019 4:07 pm
Location: southern oregon

Re: SPINDLE SERVO SPECS

Post by turbothis » Wed Apr 03, 2019 4:59 pm

yes sorry
i want to limit what the Spindle can be commanded to do

this is the velocity value in the C program yes?

User avatar
TomKerekes
Posts: 986
Joined: Mon Dec 04, 2017 1:49 am

Re: SPINDLE SERVO SPECS

Post by TomKerekes » Wed Apr 03, 2019 5:09 pm

Hi turbothis,

Post your spindle programs you are using.
Regards,

Tom Kerekes
Dynomotion, Inc.

turbothis
Posts: 165
Joined: Fri Mar 15, 2019 4:07 pm
Location: southern oregon

Re: SPINDLE SERVO SPECS

Post by turbothis » Wed Apr 03, 2019 5:18 pm

i have not added in any spindle details as that was step 2 of getting the main program running
i have the Z axis disabled for now too

Code: Select all

#include "KMotionDef.h"

// Home and set the commutation for a 3 phase brushless motor // that is driven using two DAC Outputs // // Phase rotates until index mark is located and Encoder Zeroed 

// Function definitions

// x must be in the range 0->1 returns sin(x) and sin(x+120 degrees)

float Sine3PH (float x, float *sin2);

// put a voltage v on a 3 Phase motor at specified commutation angle

void Write3PH_DACs(CHAN *chx, float v, double angle_in_cycles); 

// return fractional part of a huge number accurately

float fractionf(double v);

// Main function entry point

void main()
{
                float k=0,A=500;   // set coil current amplitude DAC units
                double p0;
 
        ch0->InputMode=ENCODER_MODE;
	ch0->OutputMode=NO_OUTPUT_MODE;
	ch0->Vel=5000;
	ch0->Accel=5000000;
	ch0->Jerk=30000000;
	ch0->P=3;
	ch0->I=0;
	ch0->D=20;
	ch0->FFAccel=0;
	ch0->FFVel=0;
	ch0->MaxI=200;
	ch0->MaxErr=1e+006;
	ch0->MaxOutput=2000;
	ch0->DeadBandGain=1;
	ch0->DeadBandRange=0;
	ch0->InputChan0=0;
	ch0->InputChan1=0;
	ch0->OutputChan0=1;
	ch0->OutputChan1=0;
	ch0->MasterAxis=-1;
	ch0->LimitSwitchOptions=0x0;
	ch0->SoftLimitPos=1e+030;
	ch0->SoftLimitNeg=-1e+030;
	ch0->InputGain0=-1;
	ch0->InputGain1=1;
	ch0->InputOffset0=0;
	ch0->InputOffset1=0;
	ch0->OutputGain=1;
	ch0->OutputOffset=0;
	ch0->SlaveGain=1;
	ch0->BacklashMode=BACKLASH_OFF;
	ch0->BacklashAmount=0;
	ch0->BacklashRate=0;
	ch0->invDistPerCycle=0.0004;
	ch0->Lead=0;
	ch0->MaxFollowingError=1000000;
	ch0->StepperAmplitude=20;

	ch0->iir[0].B0=1;
	ch0->iir[0].B1=0;
	ch0->iir[0].B2=0;
	ch0->iir[0].A1=0;
	ch0->iir[0].A2=0;

	ch0->iir[1].B0=1;
	ch0->iir[1].B1=0;
	ch0->iir[1].B2=0;
	ch0->iir[1].A1=0;
	ch0->iir[1].A2=0;

	ch0->iir[2].B0=1;
	ch0->iir[2].B1=0;
	ch0->iir[2].B2=0;
	ch0->iir[2].A1=0;
	ch0->iir[2].A2=0;

        ch1->InputMode=ENCODER_MODE;
	ch1->OutputMode=NO_OUTPUT_MODE;
	ch1->Vel=5000;
	ch1->Accel=5000000;
	ch1->Jerk=30000000;
	ch1->P=4;
	ch1->I=0;
	ch1->D=30;
	ch1->FFAccel=0;
	ch1->FFVel=0;
	ch1->MaxI=200;
	ch1->MaxErr=1e+006;
	ch1->MaxOutput=2000;
	ch1->DeadBandGain=1;
	ch1->DeadBandRange=0;
	ch1->InputChan0=1;
	ch1->InputChan1=1;
	ch1->OutputChan0=2;
	ch1->OutputChan1=3;
	ch1->MasterAxis=-1;
	ch1->LimitSwitchOptions=0x0;
	ch1->SoftLimitPos=1e+030;
	ch1->SoftLimitNeg=-1e+030;
	ch1->InputGain0=-1;
	ch1->InputGain1=1;
	ch1->InputOffset0=0;
	ch1->InputOffset1=0;
	ch1->OutputGain=1;
	ch1->OutputOffset=0;
	ch1->SlaveGain=1;
	ch1->BacklashMode=BACKLASH_OFF;
	ch1->BacklashAmount=0;
	ch1->BacklashRate=0;
	ch1->invDistPerCycle=0.0004;
	ch1->Lead=0;
	ch1->MaxFollowingError=1000000;
	ch1->StepperAmplitude=20;

	ch1->iir[0].B0=1;
	ch1->iir[0].B1=0;
	ch1->iir[0].B2=0;
	ch1->iir[0].A1=0;
	ch1->iir[0].A2=0;

	ch1->iir[1].B0=1;
	ch1->iir[1].B1=0;
	ch1->iir[1].B2=0;
	ch1->iir[1].A1=0;
	ch1->iir[1].A2=0;

	ch1->iir[2].B0=1;
	ch1->iir[2].B1=0;
	ch1->iir[2].B2=0;
	ch1->iir[2].A1=0;
	ch1->iir[2].A2=0;



	ch2->InputMode=ENCODER_MODE;
	ch2->OutputMode=NO_OUTPUT_MODE;
	ch2->Vel=  296811.5942028985507246;
	ch2->Accel=5000000;
	ch2->Jerk= 5000000;
	ch2->P=15;
	ch2->I=0;
	ch2->D=20;
	ch2->FFAccel=0;
	ch2->FFVel=0;
	ch2->MaxI=200;
	ch2->MaxErr=1e+006;
	ch2->MaxOutput=2000;
	ch2->DeadBandGain=1;
	ch2->DeadBandRange=0;
	ch2->InputChan0=2;
	ch2->InputChan1=2;
	ch2->OutputChan0=5;
	ch2->OutputChan1=4;
	ch2->MasterAxis=-1;
	ch2->LimitSwitchOptions=0x0;
	ch2->SoftLimitPos=1e+030;
	ch2->SoftLimitNeg=-1e+030;
	ch2->InputGain0=-1;
	ch2->InputGain1=1;
	ch2->InputOffset0=0;
	ch2->InputOffset1=0;
	ch2->OutputGain=1;
	ch2->OutputOffset=0;
	ch2->SlaveGain=1;
	ch2->BacklashMode=BACKLASH_OFF;
	ch2->BacklashAmount=0;
	ch2->BacklashRate=0;
	ch2->invDistPerCycle=0.0003662109375;
	ch2->Lead=0;
	ch2->MaxFollowingError=1000000;
	ch2->StepperAmplitude=20;

	ch2->iir[0].B0=1;
	ch2->iir[0].B1=0;
	ch2->iir[0].B2=0;
	ch2->iir[0].A1=0;
	ch2->iir[0].A2=0;

	ch2->iir[1].B0=1;
	ch2->iir[1].B1=0;
	ch2->iir[1].B2=0;
	ch2->iir[1].A1=0;
	ch2->iir[1].A2=0;

	ch2->iir[2].B0=1;
	ch2->iir[2].B1=0;
	ch2->iir[2].B2=0;
	ch2->iir[2].A1=0;
	ch2->iir[2].A2=0;


               

                // rotate until we find the index mark
                // Use f0 and f1 and f2 to flag when index found for ch0 and ch1 and ch2->
                // Break out when both indexes found (f0=1 and f1=1 and f2=1)

                ch0->Enable=FALSE;
                ch1->Enable=FALSE;
                ch2->Enable=FALSE;

                int f0,f1,f2;		// Index found flags
				f0=0;f1=0;f2=0;		// Set all to index not found

                for (;;)		//Indefinite loop
                {
				if (f0==1 && f1==1 && f2==1) break;		// Done if all indexes found


     //
                   if (f0==0)				// If Ch0 index not found
				  {
				                    WaitNextTimeSlice();

                                    Write3PH_DACs(ch0,A, ++k/10000.0);  // move the pole 

                                    if (ReadBit(36))  // check for index mark ch0
                                    {

                                                p0=ch0->Position; // Index found so save position
                                                ch0->Position=0;  // set current position to Zero

                                                ch0->CommutationOffset = 658;  // from auto phase find
                                             
                                                printf("Position ch0 = %f\n",p0);

                                                f0=1;		// Mark as ch0 index found

                                    }  // End readbit
                   }  // End if f0=0
  
       //         

                   if (f1==0)				// If Ch1 index not found
				  {
				                WaitNextTimeSlice();

                                Write3PH_DACs(ch1,A, ++k/10000.0);  // move the pole 

                                if (ReadBit(37))  // check for index mark ch1
				                {
                                                p0=ch1->Position; // Index found so save position
                                                ch1->Position=0;  // set current position to Zero

                                                ch1->CommutationOffset = 658;  // from auto phase find
                                                printf("Position ch1 = %f\n",p0);

                                                f1=1;		// Mark as ch1 index found

                                    }  // End readbit
                         }  // End f1=0

        //

                    if (f2==0)				// If Ch2 index not found
				  {
				                WaitNextTimeSlice();

                                Write3PH_DACs(ch2,A, ++k/10000.0);  // move the pole 

                                if (ReadBit(38))  // check for index mark ch2
				                {
                                                p0=ch2->Position; // Index found so save position
                                                ch2->Position=0;  // set current position to Zero

                                                ch2->CommutationOffset = 1920;  // from auto phase find
                                                printf("Position ch2 = %f\n",p0);

                                                f2=1;		// Mark as ch2 index found

                                    }  // End readbit
                         }  // End f2=0


                    }  // End for loop
                

                EnableAxisDest(0,0.0f);  // Enable servo at destination of 0   X axis
              //  EnableAxisDest(1,0.0f);  // Enable servo at destination of 0   Z axis
                EnableAxisDest(2,0.0f);  // Enable servo at destination of 0   A axis

                DefineCoordSystem(0,-1,-1,2); // define which axes are in use

                // Loop forever outputting Servo output to dual DAC_SERVO_MODE

                for (;;)
             
                {
                                WaitNextTimeSlice();

                                if (ch0->Enable)  // if axis enabled commutate and output else command zero to DACs

                                                Write3PH_DACs(ch0,ch0->Output, (ch0->Position + ch0->CommutationOffset) * ch0->invDistPerCycle);                           
                                else
                                                Write3PH_DACs(ch0, 0.0,0.0);

                                if (ch1->Enable)  // if axis enabled commutate and output else command zero to DACs

                                                Write3PH_DACs(ch1,ch1->Output, (ch1->Position + ch1->CommutationOffset) * ch1->invDistPerCycle);                           
                                else
                                                Write3PH_DACs(ch1, 0.0,0.0);  


                                 if (ch2->Enable)  // if axis enabled commutate and output else command zero to DACs

                                                Write3PH_DACs(ch2,ch2->Output, (ch2->Position + ch2->CommutationOffset) * ch2->invDistPerCycle);                           
                                else
                                                Write3PH_DACs(ch2, 0.0,0.0);                 

                }  // End for loop

} // End main()

                // put a voltage v on a 3 Phase motor at specified commutation angle

                void Write3PH_DACs(CHAN *chx, float v, double angle_in_cycles)

                {

                float theta,sin1f;
                if (angle_in_cycles<0)

                                theta = 1.0f-fractionf(-angle_in_cycles);

                else

                                theta = fractionf(angle_in_cycles);


                DAC(chx->OutputChan0, (int)(v * Sine3PH(theta,&sin1f)));
                DAC(chx->OutputChan1, (int)(v * sin1f));

               }  // End Write3PH()

User avatar
TomKerekes
Posts: 986
Joined: Mon Dec 04, 2017 1:49 am

Re: SPINDLE SERVO SPECS

Post by TomKerekes » Wed Apr 03, 2019 10:11 pm

Hi turbothis,

You will need to figure out what kind of Spindle you have and how it will be interfaced before we can help you.

You might see this.
Regards,

Tom Kerekes
Dynomotion, Inc.

turbothis
Posts: 165
Joined: Fri Mar 15, 2019 4:07 pm
Location: southern oregon

Re: SPINDLE SERVO SPECS

Post by turbothis » Mon Apr 08, 2019 6:33 pm

well i am running my A axis servo/spindle with the dual DAC outputs

it has 11872.46 counts per rev
so i am thinking this program

Code: Select all

#include "KMotionDef.h"

#define SPINDLEAXIS 4
#define FACTOR (1187246.0/6000) //   counts per second  =  RPM

// desired speed is passed in variable 1
// save in user variable 99 the last speed setting
// save in user variable 98 whether it was off, CW, or CCW (0,1,-1)
// save in user variable 97 the last desired speed


main()
{
	float speed = *(float *)&persist.UserData[1];  // value stored is actually a float 
	float LastSpeed = *(float *)&persist.UserData[99];  // get last speed setting 
	float LastState = persist.UserData[98];  // get last state 
	
	if (LastState==0)  
	{
		// if spindle is off and User Changes the speed 
		// just save the desired speed
		
		persist.UserData[97] = persist.UserData[1];
		return 0;
	}
	
	// spindle is already on, so ramp to new speed
	
	if (LastSpeed != speed)
	{
		LastSpeed = speed;
		Jog(4,LastSpeed * FACTOR);
	}
	
	*(float *)&persist.UserData[99] = LastSpeed;
}
with this being run with dual DAC's does the jog program need to be in the axis enable program?

and i am thinking to just have M5 zero output to the DAC's?

Code: Select all

#include "KMotionDef.h"



main()
{
	DAC(4, 0); 
	DAC(5, 0); 
	
}


User avatar
TomKerekes
Posts: 986
Joined: Mon Dec 04, 2017 1:49 am

Re: SPINDLE SERVO SPECS

Post by TomKerekes » Mon Apr 08, 2019 8:04 pm

Hi turbothis,

Since your spindle can be operated as an axis I'd recommend you base your code on the newer \SpindleUsingJogs\SpindleOnCWJogV2.c.

To stop the Spindle (M5) use \SpindleUsingJogs\SpindleOffJogV2.c. This will permit a decelerated and controlled stop. Writing to the DACs wouldn't work as your Dual DAC code would immediately overwrite the DAC with new values as it is writing continuously.

You can then add an if condition to limit the speed value.
Regards,

Tom Kerekes
Dynomotion, Inc.

Post Reply