Dynomotion

Group: DynoMotion Message: 5564 From: Michael Rosenfield Date: 8/17/2012
Subject: MPG
Tom,
I got the MPG working now, but there is a new issue:
I changed the sign of the encoder and output on the x & y axes so that they match the output signs of my CAM software, but now the jog buttons on the KMotionCNC screen point opposite to machine travel.
How can I fix this?
 
Thanks,
Michael Rosenfield 
 
 
 
 

 
Group: DynoMotion Message: 5565 From: Tom Kerekes Date: 8/17/2012
Subject: Re: MPG
Hi Mike,
 
That doesn't seem logical.  If the GCode has +X moving the cutting tool to the right then the Jog Arrow button pointing to the right should move the cutting tool to the right.
 
Maybe the confusion is that with some (most) systems instead of the cutting tool moving to the right the table moves to the left which results in the same effect.  Is thi what you are referring to?
 
Regards
TK

Group: DynoMotion Message: 5566 From: Michael Rosenfield Date: 8/17/2012
Subject: Re: MPG
Yes, I guess that is exactly it - I'm confusing table motion with cutter motion.
Thanks for straightening that out.
It has been a lot of years since I've run a CNC mill, and I thought I remembered how the one I used to run behaved.
 
Another question: in running the old machine, we used to set tool length by inserting each tool and manually bringing each tool down to the part Z0, and pushing a 'set' button on the controller.
How is this process supposed to work with KMotionCNC?
Thanks again, Tom!
 Michael
Group: DynoMotion Message: 5568 From: Tom Kerekes Date: 8/17/2012
Subject: Re: MPG
Hi Mike,
 
There are many methods of using offsets.  I'm probably not the best one to answer.
 
But KMotionCNC has a "Zero" button for Z that will set a global G92 offset so that the current tool position becomes zero.  I would think that would do as you describe.
 
Regards
TK

Group: DynoMotion Message: 14693 From: janbbeck Date: 5/8/2017
Subject: MPG
Hi, I am working on an MPG for my lathe and working off the MPGSmoothHardwareEnc.c example.

In the code there are places like this:

if (ReadBit(SELECTX))  // is x selected?
      Axis=0;
    else if (ReadBit(SELECTY))  // is y selected?
      Axis=1;
    else if (ReadBit(SELECTZ))  // is z selected?
      Axis=2;


which is fine, but I like to take advantage of error detection and diagnosis whenever possible, so I am planning on doing it like this:


if ((1 == ReadBit(SELECTX)) &&(0 == ReadBit(SELECTY)) &&(0 == ReadBit(SELECTZ)) )  // is x selected?
      Axis=0;
    else if (
(0 == ReadBit(SELECTX)) &&(1 == ReadBit(SELECTY)) &&(0 == ReadBit(SELECTZ)))  // is y selected?
      Axis=1;
    else if (
(0 == ReadBit(SELECTX)) &&(0 == ReadBit(SELECTY)) &&(1 == ReadBit(SELECTZ)))  // is z selected?
      Axis=2;

else

    // ERROR MESSAGE and disable wheel


This way, I can diagnose an unintended hardware state and even send a message to the effect of "Loose wire or something in MPG selection knob". Otherwise, I can see a loose connection causing the MPG to change axes while spinning the wheel.


My question is what the best way is of sending the error message on. I suppose a printf will send it to the console, but a popup window in the KMotionCNC, would be better.


Suggestions?


Group: DynoMotion Message: 14694 From: Tom Kerekes Date: 5/8/2017
Subject: Re: MPG

See the example MessageBox.c for how to pop up a message box from KFLOP.  Note that this example will block until the operator responds which might be a problem if your loop is doing anything critical that needs continuous service.  There is an example MessageBoxNoWait.c which sends the MessageBox request but doesn't wait for a response.

Depending on how your switch works and debounces and such there may be other valid states to consider that may be valid such as none selected.

HTH

Regards

TK



On 5/8/2017 4:28 PM, homeloan@... [DynoMotion] wrote:
 

Hi, I am working on an MPG for my lathe and working off the MPGSmoothHardwareEnc.c example.

In the code there are places like this:

if (ReadBit(SELECTX))  // is x selected?
      Axis=0;
    else if (ReadBit(SELECTY))  // is y selected?
      Axis=1;
    else if (ReadBit(SELECTZ))  // is z selected?
      Axis=2;


which is fine, but I like to take advantage of error detection and diagnosis whenever possible, so I am planning on doing it like this:


if ((1 == ReadBit(SELECTX)) &&(0 == ReadBit(SELECTY)) &&(0 == ReadBit(SELECTZ)) )  // is x selected?
      Axis=0;
    else if (
(0 == ReadBit(SELECTX)) &&(1 == ReadBit(SELECTY)) &&(0 == ReadBit(SELECTZ)))  // is y selected?
      Axis=1;
    else if (
(0 == ReadBit(SELECTX)) &&(0 == ReadBit(SELECTY)) &&(1 == ReadBit(SELECTZ)))  // is z selected?
      Axis=2;

else

    // ERROR MESSAGE and disable wheel


This way, I can diagnose an unintended hardware state and even send a message to the effect of "Loose wire or something in MPG selection knob". Otherwise, I can see a loose connection causing the MPG to change axes while spinning the wheel.


My question is what the best way is of sending the error message on. I suppose a printf will send it to the console, but a popup window in the KMotionCNC, would be better.


Suggestions?



Group: DynoMotion Message: 14699 From: janbbeck Date: 5/8/2017
Subject: Re: MPG
I am having a problem. The MPG wheel does not seem to be recognized in the program.

The bits for the switch positions all seem to work. I connected the MPG to hardware encoder channel 3 and after doing this:

ch1->InputChan0 = 3; // shows encoder count on Axis window using unused channel

I can see the MPG changing the Position field of channel 1 in the Axis window of Kmotion.

However, accessing the position member from within the program does not seem to work.

this operation:
Pos = chan[MPG_INPUT_AXIS].Position;

always yields zero, as far as I can tell.

I tried this:
Pos = ch1->Position;

with the same result.

I even printed all the channels to the console:
  printf("0 %d\n",chan[0].Position);
  printf("1 %d\n",chan[1].Position);
  printf("2 %d\n",chan[2].Position);
  printf("3 %d\n",chan[3].Position);
  printf("4 %d\n",chan[4].Position);
  printf("5 %d\n",chan[5].Position);
  printf("6 %d\n",chan[6].Position);
  printf("7 %d\n",chan[7].Position);

they all print zero, regardless of what I do to the MPG.

I am probably misunderstanding some channel mapping, as suggested here:
http://www.dynomotion.com/wiki/index.php?title=Channels_Channels_Channels

I looked at the stucture definition of CHAN in kmotiondef.h, but that just confused me, because inside it,

//  M A I N   S T R U C T U R E   T H A T   D E F I N E S   A N   A X I S

typedef struct
{  
    int ChanNumber;                 // channel number 0-3
   ........
}CHAN;


so, CHAN defines a structure for an axis (as expected there are 8 of those in the array chan[]), and each axis has 4 channels (ChanNumber) of what exactly?

I am pasting the whole here, just in case:

 
#include "KMotionDef.h"
 
// Configure SnapAMP for 2 stepper motors in Optical Table Lathe
 
#define MPG_INPUT_AXIS 3
 
#define TAU 0.08 // smoothness factor (Low Pass Time constant seconds)
#define FINAL_TIME 1.0 // Set final dest after this amount of time with no change
 
#define ENABLE_MPG 92
 
#define SELECTX 93
#define SELECTZ 86
 
#define FACTOR1 88 
#define FACTOR10 89
#define FACTOR100 90
 
int counter = 0;
 
void main() 
{
     
    WriteSnapAmp(SNAP0+SNAP_PEAK_CUR_LIMIT0,9);  // current limit
    WriteSnapAmp(SNAP0+SNAP_PEAK_CUR_LIMIT1,10);  // current limit
    Delay_sec(0.1);  // wait for any fault to clear
 
    ch1->InputChan0 = 3; // shows encoder count on Axis window using unused channel
    ch2->InputChan0 = 10; // shows encoder count on Axis window using unused channel
    ch3->InputChan0 = 11; // shows encoder count on Axis window using unused channel
 
 
    ch4->InputMode=NO_INPUT_MODE;
    ch4->OutputMode=MICROSTEP_MODE;
    ch4->Vel=200.000000;
    ch4->Accel=5000.000000;
    ch4->Jerk=50000.000000;
    ch4->P=1.000000;
    ch4->I=0.000000;
    ch4->D=0.000000;
    ch4->FFAccel=0.000000;
    ch4->FFVel=0.000000;
    ch4->MaxI=200.000000;
    ch4->MaxErr=1000000.000000;
    ch4->MaxOutput=200.000000;
    ch4->DeadBandGain=1.000000;
    ch4->DeadBandRange=0.000000;
    ch4->InputChan0=8;
    ch4->InputChan1=9;
    ch4->OutputChan0=8;
    ch4->OutputChan1=9;
    ch4->LimitSwitchOptions=0x0;
    ch4->InputGain0=1.000000;
    ch4->InputGain1=1.000000;
    ch4->InputOffset0=0.000000;
    ch4->InputOffset1=0.000000;
    ch4->invDistPerCycle=1.000000;
    ch4->Lead=0.000000;
    ch4->MaxFollowingError=1000000000.000000;
    ch4->StepperAmplitude=35.000000;
    
    
    ch4->iir[0].B0=1.000000;
    ch4->iir[0].B1=0.000000;
    ch4->iir[0].B2=0.000000;
    ch4->iir[0].A1=0.000000;
    ch4->iir[0].A2=0.000000;
 
    ch4->iir[1].B0=1.000000;
    ch4->iir[1].B1=0.000000;
    ch4->iir[1].B2=0.000000;
    ch4->iir[1].A1=0.000000;
    ch4->iir[1].A2=0.000000;
 
    ch4->iir[2].B0=1.000000;
    ch4->iir[2].B1=0.000000;
    ch4->iir[2].B2=0.000000;
    ch4->iir[2].A1=0.000000;
    ch4->iir[2].A2=0.000000;
 
    EnableAxisDest(4, 0.0);
 
    ch5->InputMode=NO_INPUT_MODE;//ENCODER_MODE;
    ch5->OutputMode=MICROSTEP_MODE;
    ch5->Vel=  300;//20000.000000;
    ch5->Accel=2000;//100000.000000;
    ch5->Jerk= 20000;//2000000.000000;
    ch5->P=1;//0.40000;
    ch5->I=0;//.000300;
    ch5->D=0;//.000000;
    ch5->FFAccel=0.000000;
    ch5->FFVel=0.000000;
    ch5->MaxI=200.000000;
    ch5->MaxErr=50.000000;
    ch5->MaxOutput=1e10;//1000.000000;
    ch5->DeadBandGain=0.0500000;
    ch5->DeadBandRange=2.000000;
    ch5->InputChan0=10; // 8 is snapamp0 ch0; 0 is kflop ch0 (JP7 pin7&8)
    ch5->InputChan1=11;
    ch5->OutputChan0=10;
    ch5->OutputChan1=11;
    ch5->LimitSwitchOptions=0x0;
    ch5->InputGain0=1.000000;
    ch5->InputGain1=1.000000;
    ch5->InputOffset0=0.000000;
    ch5->InputOffset1=0.000000;
    ch5->invDistPerCycle=-1.000000;
    ch5->Lead=0.000000;
    ch5->MaxFollowingError=100.000000;
    ch5->StepperAmplitude=50.000000;
 
    ch5->iir[0].B0=1.000000;
    ch5->iir[0].B1=0.000000;
    ch5->iir[0].B2=0.000000;
    ch5->iir[0].A1=0.000000;
    ch5->iir[0].A2=0.000000;
 
    ch5->iir[1].B0=1.000000;
    ch5->iir[1].B1=0.000000;
    ch5->iir[1].B2=0.000000;
    ch5->iir[1].A1=0.000000;
    ch5->iir[1].A2=0.000000;
 
    ch5->iir[2].B0=1.0;//0.0566048;
    ch5->iir[2].B1=0.0;//0.11321;
    ch5->iir[2].B2=0.0;//0.0566048;
    ch5->iir[2].A1=0.0;//1.22804;
    ch5->iir[2].A2=0.0;//-0.454462;
 
 
     
    DefineCoordSystem(4,-1,5,-1); //define ch4 as x and ch5 as y; z and a disabled
/*
    DisableAxis(5);
    ch5->Vel=  50000.000000;
    ch5->Accel=2000000.000000;
    ch5->Jerk= 4000000.000000;
    //ch5->P=0.40000;
    //ch5->I=0.000500;
    //ch5->D=7.000000;
    ch5->P=0.50000;
    ch5->I=0.000000;
    ch5->D=0.000000;
    
    Write4PH(ch5,100,0);      // energize a pole
    Delay_sec(2);          // wait     
    Zero(5);
       ch5->InputMode=ENCODER_MODE;
    ch5->OutputMode=BRUSHLESS_4PH_MODE;
    //ch5->CommutationOffset = 0.25 * 20000/50 + 4;  // offset ~1/4 of encoder count per pole 
    //ch5->invDistPerCycle= 1.0 * 50.0/20000.0;  // 200 step stepper -> 50 poles; 5000 line encoder -> 20000 counts per revolution.
    ch5->CommutationOffset = 0.25 * 16384/50 + 4;  // offset ~1/4 of encoder count per pole 
    ch5->invDistPerCycle= 1.0 * 50.0/16384.0;  // 200 step stepper -> 50 poles; 4096 line encoder -> 20000 counts per revolution.
  */  
  EnableAxisDest(5, 0.0);
  Zero(5);
 
  int Change1, NewPos, Pos;
  int InMotion=FALSE,Axis,LastAxis=-1;
  double LastChangeTime=0,Target,Factor=0;
  
  Pos = ch1->Position;//chan[MPG_INPUT_AXIS].Position;
 
for (;;) // forever
  {
      counter++;
    NewPos = ch1->Position;//chan[MPG_INPUT_AXIS].Position;
    
    Change1 = NewPos - Pos;
    Pos = NewPos;
 
    if (1 == ReadBit(ENABLE_MPG)) // if rotary knob is on 'off' this bit is high
      {
      Change1 = 0;
      if (counter > 1000)
      {
          counter = 0;
      printf("e\n");
      }
      }
    else if (ReadBit(FACTOR1))  // is X1 selected?
          {
      Change1 = 0;
      if (counter > 1000)
      {
          counter = 0;
      printf("2\n");
      }
      Factor = 2;
      }
    else if (ReadBit(FACTOR10))  // is X10 selected?
          {
      Change1 = 0;
      if (counter > 1000)
      {
          counter = 0;
      printf("20\n");
      }
      Factor = 20;
      }
    else if (ReadBit(FACTOR100))  // is X100 selected?
          {
      Change1 = 0;
      if (counter > 1000)
      {
          counter = 0;
      printf("200\n");
      }
      Factor = 200;
      }
    else                  
          {
      Change1 = 0;
      if (counter > 1000)
      {
          counter = 0;
      printf("0\n");
      }
      Factor = 0.0;
      }
 
    if (ReadBit(SELECTX))  // is x selected?
    {
      Axis=4;
      }
    else if (ReadBit(SELECTZ))  // is z selected?
    {
      Axis=5;
      }
 
    // check if the Axis just changed or we have been
    // converging to the target for a long time
    if (Axis != LastAxis ||(InMotion && Time_sec() > LastChangeTime+FINAL_TIME))
    {
  printf("0 %d\n",chan[0].Position);
  printf("1 %d\n",ch1->Position);//chan[1].Position);
  printf("2 %d\n",chan[2].Position);
  printf("3 %d\n",chan[3].Position);
  printf("4 %d\n",chan[4].Position);
  printf("5 %d\n",chan[5].Position);
  printf("6 %d\n",chan[6].Position);
  printf("7 %d\n",chan[7].Position);
      if (InMotion)
        Move(LastAxis,Target);  //finalize any motion
 
      LastAxis = Axis;
      InMotion = FALSE;
    }
   
    if (Change1) // did we move?
    {
      printf("if2\n");
      if (!InMotion) Target = chan[Axis].Dest;
      Target += Change1 * Factor;
      MoveExp(Axis,Target,TAU);  // note: contains a WaitNextTimeSlice
      LastChangeTime = Time_sec();
      InMotion=TRUE;
    }
    else
    {
      WaitNextTimeSlice();
    }   
  } 
 
 
}
Group: DynoMotion Message: 14700 From: Tom Kerekes Date: 5/8/2017
Subject: Re: MPG

Hi,

chan[1].Position is a double precision floating point number.  So to print it use %f not %d.  Use %d to print integers in decimal.  That might be why it prints zero.  If the Position for Axis #1 changes properly on the Axis Screen it should print the same thing.


This is an error in the comment.  Leftover from ~10 years ago when our Controller was 4 axes (sorry about that)

typedef struct
{  
    int ChanNumber;                 // channel number 0-3
   ........
}CHAN;

it should say 0-7.  ChanNumber is rarely needed or used.  It is there for convenience when you happen to have a memory pointer to some Axis Structure and want to find out which Axis Number it is pointing to.  So among all the data for an Axis Channel is also the Axis Channel Number.  


It seems you have every "if" condition setting Change1 to zero.  Change1 is the calculation of how much the encoder Position Changed since the last time it was sampled.  Forcing it to zero will result in no motion.


HTH

Regards

TK


On 5/8/2017 10:24 PM, homeloan@... [DynoMotion] wrote:
 

I am having a problem. The MPG wheel does not seem to be recognized in the program.

The bits for the switch positions all seem to work. I connected the MPG to hardware encoder channel 3 and after doing this:

ch1->InputChan0 = 3; // shows encoder count on Axis window using unused channel

I can see the MPG changing the Position field of channel 1 in the Axis window of Kmotion.

However, accessing the position member from within the program does not seem to work.

this operation:
Pos = chan[MPG_INPUT_AXIS].Position;

always yields zero, as far as I can tell.

I tried this:
Pos = ch1->Position;

with the same result.

I even printed all the channels to the console:
  printf("0 %d\n",chan[0].Position);
  printf("1 %d\n",chan[1].Position);
  printf("2 %d\n",chan[2].Position);
  printf("3 %d\n",chan[3].Position);
  printf("4 %d\n",chan[4].Position);
  printf("5 %d\n",chan[5].Position);
  printf("6 %d\n",chan[6].Position);
  printf("7 %d\n",chan[7].Position);

they all print zero, regardless of what I do to the MPG.

I am probably misunderstanding some channel mapping, as suggested here:
http://www.dynomotion.com/wiki/index.php?title=Channels_Channels_Channels

I looked at the stucture definition of CHAN in kmotiondef.h, but that just confused me, because inside it,

//  M A I N   S T R U C T U R E   T H A T   D E F I N E S   A N   A X I S

typedef struct
{  
    int ChanNumber;                 // channel number 0-3
   ........
}CHAN;


so, CHAN defines a structure for an axis (as expected there are 8 of those in the array chan[]), and each axis has 4 channels (ChanNumber) of what exactly?


Group: DynoMotion Message: 14701 From: janbbeck Date: 5/8/2017
Subject: Re: MPG
Thanks for the detailed explanation. I have a working MPG now!
I sure is nice to be able to use the wheel instead of contorting back and forth between computer and lathe :)

Right now, I have to assign the encoder to an unused axis just to be able to read its value. Is that strictly necessary or are the encoders available via a variable other than chan?