need serious help again

Moderators: TomKerekes, dynomotion

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

Re: need serious help again

Post by turbothis » Mon Mar 18, 2019 8:45 pm

what does make the signal hi/low?
i will load a fresh version of it and insert my info again
maybe i went and jumbled up some info on it

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

Re: need serious help again

Post by TomKerekes » Mon Mar 18, 2019 9:42 pm

Hi turbothis,

An input will be high or low depending on the physical voltage on the pin. There is nothing that can be configured to change this - short of changing it from an input to an output and then driving it high or low.

JP5 IO (IO36 - IO43) do not have any pull down or pull up resistors and have very high input impedance so if unconnected can float high or low more or less randomly dependent on parasitic resistance or capacitance to other signals.

Any unconnected/non-driven input should be ignored and not used by your program.
Regards,

Tom Kerekes
Dynomotion, Inc.

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

Re: need serious help again

Post by turbothis » Mon Mar 18, 2019 10:14 pm

ok i will slim down the program to one channel only and see what happens
thanks a million as always!

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

Re: need serious help again

Post by turbothis » Tue Mar 19, 2019 1:50 am

so a couple more hours trying this out with no progress
i have a dual DAC C program i use for my 4th axis on my mill and it works perfect
it is a single servo that uses this.

i punched in the new info into this and got the same outcome
the servo starts to find Z and then spins a couple times real fast and then disables......

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 *ch0, float v, double angle_in_cycles); 

// return fractional part of a huge number accurately
float fractionf(double v);

void main() 
{
	float k=0,A=500;   // set coil current amplitude DAC units
	double p0;

	// define the axis as 3 phase BRUSHLESS_3PH_MODE
	

	ch0->InputMode=ENCODER_MODE;
	ch0->OutputMode=NO_OUTPUT_MODE;
	ch0->Vel=40000;
	ch0->Accel=400000;
	ch0->Jerk=4e+06;
	ch0->P=1;
	ch0->I=0;
	ch0->D=10;
	ch0->FFAccel=0;
	ch0->FFVel=0;
	ch0->MaxI=200;
	ch0->MaxErr=1e+06;
	ch0->MaxOutput=1000;
	ch0->DeadBandGain=1;
	ch0->DeadBandRange=0;
	ch0->InputChan0=0;
	ch0->InputChan1=0;
	ch0->OutputChan0=0;
	ch0->OutputChan1=1;
	ch0->MasterAxis=-1;
	ch0->LimitSwitchOptions=0x100;
	ch0->LimitSwitchNegBit=0;
	ch0->LimitSwitchPosBit=0;
	ch0->SoftLimitPos=1e+09;
	ch0->SoftLimitNeg=-1e+09;
	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.000400641026;
	ch0->Lead=0;
	ch0->MaxFollowingError=500000;
	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=0.000769;
	ch0->iir[2].B1=0.001538;
	ch0->iir[2].B2=0.000769;
	ch0->iir[2].A1=1.92081;
	ch0->iir[2].A2=-0.923885;

	// rotate until we find the index mark

	ch0->Enable=FALSE;
	for (;;)
	{
		WaitNextTimeSlice();

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

		if (ReadBit(36))  // check for index mark
		{
			p0=ch0->Position; // save position
			ch0->Position=0;  // set current position to Zero

			ch0->CommutationOffset = 2125;  // from auto phase find

			printf("Position = %f\n",p0);
			break;
		}
	}

	EnableAxisDest(0,0.0f);  // Enable servo at destination of 0
	DefineCoordSystem(0,-1,-2,-3); // define which axes are in use

	// Loop forever outputting Servo output to dual DAC_SERVO_MODE

	for (;;)
	{
		CHAN *ch=ch0;

		if (ch->Enable)  // if axis enabled commutate and output else command zero to DACs
			Write3PH_DACs(ch, ch->Output, (ch->Position + ch->CommutationOffset) * ch->invDistPerCycle);		
		else
			Write3PH_DACs(ch, 0.0, 0.0);		
	}
}


// put a voltage v on a 3 Phase motor at specified commutation angle
void Write3PH_DACs(CHAN *ch, 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(ch->OutputChan0, (int)(v * Sine3PH(theta,&sin1f)));
	DAC(ch->OutputChan1, (int)(v * sin1f));
}



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

Re: need serious help again

Post by TomKerekes » Tue Mar 19, 2019 4:05 pm

Hi turbothis,

I see another bug in AutoPhaseFindDualDACs.c there is a 20000.0 that should be 2000.0 that would compute the completely wrong commutation offset.

Also the ch0->invDistPerCycle=0.0004 is still not entered correctly.

What gets printed on the console?

It would be helpful if you put some effort into troubleshooting what is working and what is not and posting back the information. I'd suggest setting very low max output (100 DAC counts?) and very low gains (P=0.01 I=0 D=0 Clear all Filters). In this case the motor should first rotate to the Index mark. Is it doing this? The motor should then remain still and servo at that position. With the very low gain rotating the motor shaft by hand should feel like a weak spring. Rotating away 10000 counts torque should gradually increase and create a torque of 100 DAC counts back towards the starting point. (10000 counts of error x PGain 0.01 = 100 DAC counts). If commutation is working correctly the force should then remain relatively constant (100 DAC counts) as you rotate the motor further multiple revolutions.
Regards,

Tom Kerekes
Dynomotion, Inc.

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

Re: need serious help again

Post by turbothis » Tue Mar 19, 2019 5:26 pm

ok from the top! lol

i run this.....

Code: Select all

#include "KMotionDef.h"

// Drive a 3 Phase motor that has a Z index by
// 3 phase driving the coils (like a stepping motor)
// two revs each direction (two z pulses)
// monitor how many counts/cycle and counts/rev 
// (including direction)and also determine the commutation
// offset by recording the phase angle at the index 
// (which will be where zero is set) and offsetting by 1/4 of a cycle 
//
// Set the following parameters according to your situation
// See the report generated on the Console Screen

#define DAC_CHAN 0      // which pair of PWM channels used
#define ENCODER_CHAN 0  // which encoder we are connected to
#define ENCODER_GAIN 1  // Set to -1 if desired to reverse axis direction
#define AMPLITUDE 200   // Set how hard to drive the coils pwm counts
#define Z_BIT_NUMBER 36  // What bit the Z index is connected to
#define AXIS_CHAN 0     // Axis channel to be used and configured
#define Ncycles 4       // don't change this

// 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 *ch0, float v, double angle_in_cycles); 

// return fractional part of a huge number accurately
float fractionf(double v);


void main() 
{
	float mid,k=0,dk=0.2,A=AMPLITUDE;   // set coil current amplitude
	int i,ignore=300,kpos[Ncycles],zmark,m=0;
	double cnts_per_cycle,p0[Ncycles];
	CHAN *ch = &chan[AXIS_CHAN];

	// rotate until we find the index mark

	ch->Enable=FALSE;
	ch->InputMode=ENCODER_MODE;
	ch->InputChan0=ENCODER_CHAN;
	ch->OutputChan0=DAC_CHAN;
	ch->OutputChan1=DAC_CHAN+1;
	ch->OutputMode=NO_OUTPUT_MODE;
	ch->InputGain0=ENCODER_GAIN;

	for (;;)
	{
		WaitNextTimeSlice();

		k+= dk;

		Write3PH_DACs(ch,A, k/1000.0);  // move the pole 

		zmark = ReadBit(Z_BIT_NUMBER);

		if (!zmark && ignore>0) ignore--;

		if (ignore==0 && zmark)  // check for index mark
		{
			p0[m]=ch->Position;  // save position
			kpos[m]=k;           // save phase angle

			if (++m == Ncycles) 
			{
				ch->Position=0;  // set current position to Zero
				break;
			}

			if (m==2) dk = -dk;
			ignore=300;
		}
	}

	Write3PH_DACs(ch,0,0);    // turn off the coil    

	printf("\nREPORT\n------\n");
	for (i=0; i<Ncycles; i++)
		printf("%d Position = %6.0f PhaseAngle = %f\n",i,p0[i],kpos[i]/1000.0);

	printf("Counts per rev = %6.0f\n",p0[1]-p0[0]);
	cnts_per_cycle = (p0[1]-p0[0])/(kpos[1]-kpos[0])*1000.0;
	printf("Counts per cycle = %6.0f\n",cnts_per_cycle);

	// round to 16
	if (cnts_per_cycle>0)
		cnts_per_cycle = ((int)(cnts_per_cycle/16.0 + 0.5))*16.0;
	else
		cnts_per_cycle = ((int)(cnts_per_cycle/16.0 - 0.5))*16.0;

	printf("Counts per cycle (rounded to 16)= %6.0f\n",cnts_per_cycle);

	ch->invDistPerCycle = 1.0/cnts_per_cycle;
	printf("invDistPerCycle (rounded)= %15.12f\n",ch->invDistPerCycle);

	mid = (kpos[2]+kpos[1])/2000.0;
	mid = mid - (int)mid;
	ch->CommutationOffset = mid*cnts_per_cycle + 0.25*fast_fabs(cnts_per_cycle);
	printf("Commutation offset = %6.0f\n",ch->CommutationOffset);
	printf("Input Gain Specified = %6.3f\n",ch->InputGain0);
}


// put a voltage v on a 3 Phase motor at specified commutation angle
void Write3PH_DACs(CHAN *ch, 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(ch->OutputChan0, (int)(v * Sine3PH(theta,&sin1f)));
	DAC(ch->OutputChan1, (int)(v * sin1f));
}

and it prints this......

REPORT
------
0 Position = 9998 PhaseAngle = 4.028000
1 Position = 19998 PhaseAngle = 8.028000
2 Position = 10000 PhaseAngle = 4.003000
3 Position = 0 PhaseAngle = 0.003000
Counts per rev = 10000
Counts per cycle = 2500
Counts per cycle (rounded to 16)= 2496
invDistPerCycle (rounded)= 0.000400641026
Commutation offset = 663
Input Gain Specified = 1.000

REPORT
------
0 Position = 9999 PhaseAngle = 4.028000
1 Position = 19999 PhaseAngle = 8.028000
2 Position = 10000 PhaseAngle = 4.003000
3 Position = 0 PhaseAngle = 0.003000
Counts per rev = 10000
Counts per cycle = 2500
Counts per cycle (rounded to 16)= 2496
invDistPerCycle (rounded)= 0.000400641026
Commutation offset = 663
Input Gain Specified = 1.000


so i enter that into my other axis program......

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 *ch0, float v, double angle_in_cycles); 

// return fractional part of a huge number accurately
float fractionf(double v);

void main() 
{
	float k=0,A=100;   // set coil current amplitude DAC units
	double p0;

	// define the axis as 3 phase BRUSHLESS_3PH_MODE
	

	ch0->InputMode=ENCODER_MODE;
	ch0->OutputMode=NO_OUTPUT_MODE;
	ch0->Vel=400000;
	ch0->Accel=400000;
	ch0->Jerk=1e+008;
	ch0->P=0.1;
	ch0->I=0;
	ch0->D=0;
	ch0->FFAccel=0;
	ch0->FFVel=0;
	ch0->MaxI=200;
	ch0->MaxErr=1e+006;
	ch0->MaxOutput=1000;
	ch0->DeadBandGain=1;
	ch0->DeadBandRange=0;
	ch0->InputChan0=0;
	ch0->InputChan1=0;
	ch0->OutputChan0=0;
	ch0->OutputChan1=1;
	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.000400641026;
	ch0->Lead=0;
	ch0->MaxFollowingError=400000000;
	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;

	// rotate until we find the index mark

	ch0->Enable=FALSE;
	for (;;)
	{
		WaitNextTimeSlice();

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

		if (ReadBit(36))  // check for index mark
		{
			p0=ch0->Position; // save position
			ch0->Position=0;  // set current position to Zero

			ch0->CommutationOffset = 2496;  // from auto phase find

			printf("Position = %f\n",p0);
			break;
		}
	}

	EnableAxisDest(0,0.0f);  // Enable servo at destination of 0
	DefineCoordSystem(0,-1,-1,-1); // define which axes are in use

	// Loop forever outputting Servo output to dual DAC_SERVO_MODE

	for (;;)
	{
		CHAN *ch=ch0;

		if (ch->Enable)  // if axis enabled commutate and output else command zero to DACs
			Write3PH_DACs(ch, ch->Output, (ch->Position + ch->CommutationOffset) * ch->invDistPerCycle);		
		else
			Write3PH_DACs(ch, 0.0, 0.0);		
	}
}


// put a voltage v on a 3 Phase motor at specified commutation angle
void Write3PH_DACs(CHAN *ch, 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(ch->OutputChan0, (int)(v * Sine3PH(theta,&sin1f)));
	DAC(ch->OutputChan1, (int)(v * sin1f));
}


i can "run" this and it works fine but when i hit compile it says "D:\X axis.txt:1: could not read header (unknown file extention type)"

this is the best performance so far

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

Re: need serious help again

Post by turbothis » Tue Mar 19, 2019 5:48 pm

interesting.... so my program that works but wont compile, i copy and paste that into a new or existing C program and the servo just freaks out!

why does my .txt file work fine and not just transfer via copy/paste into another .c file and work?

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

Re: need serious help again

Post by TomKerekes » Tue Mar 19, 2019 6:14 pm

Hi turbothis,

The invCountsPerCycle is still incorrect. It needs to be exactly 0.0004. The Auto-phase Find Report is incorrect because it is assuming your encoder has a power of 2 as a number of counts per rev. For example 2048 counts per rev is a common resolution. It estimates the counts/cycle by dragging the motor like a crude stepping motor through a few cycles. This can have a few encoder counts of error depending on load/friction etc. So the program rounds off to a multiple of 16 which is incorrect for your encoder which has a resolution of a multiple of 100 (2500 counts/cycle). Change all "16"s to "100"s to fix this.

You did not enter the correct new Commutation Offset of 663. Note there might be a tiny change in this value after correcting the rounding described above but probably not enough to make a significant difference.

C Programs must have a *.c file extension not a .txt extension.

Never attempt to run a program that doesn't compile. Simply running a Thread will run whatever was last correctly compiled and downloaded to that Thread which is likely to be something completely unknown and different from what you want.
Regards,

Tom Kerekes
Dynomotion, Inc.

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

Re: need serious help again

Post by turbothis » Tue Mar 19, 2019 8:47 pm

i believe this is a 8 pole servo. does this have a parameter to mess with?

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

Re: need serious help again

Post by TomKerekes » Tue Mar 19, 2019 9:19 pm

Hi turbothis,

No. To commutate properly all that is required is the encoder counts per cycle. But that is why the report shows the phases going through 4 complete cycles to cause one motor revolution.
Regards,

Tom Kerekes
Dynomotion, Inc.

Post Reply