Re: Jog wheel (with code attached)


starting about a year ago I did some collaboration with Alan Marconett on 
the CCED list on the handwheel interface ,hammering out the best ways to
get the input into the control and looking into what problems might come up

the result was the pendant Alan made from junk box parts shown here
check the pendant 1 and 2 jpegs 
http://photos.groups.yahoo.com/group/cad_cam_edm_dro/lst?.dir=/Driver-PS+%26+Pendant
compare Alan's pendant with the $300-$500 versions 
http://www.maxmar.com/mpg.htm
http://www.sumtak.com/contents/product/handLGB601/indexLGB601.htm
http://www.cui.com/encoders/encd_tools.htm
functionally they are pretty much the same

for the encoder I would use one of the optical panel mount encoders 
like the CUI RE20 shown here
http://www.cui.com/encoders/encd_paneloptic.htm
available as  Digi-Key Part Number 102-1012-ND
*********IMPORTANT NOTE***********************
check the data sheet before trying to get the detented versions
of the the RE20s 
the detented version has 25 lines (100 quad transitions) with only
25 detents (4 transitions per detent) lined up with the A&B high phase
this is not what we you want
instead get the non-detented encoder and build the detents into
the knob using an index plate with 100 dimples and a spring pin under
the handwheel knob 
***************************************************

the code I've attached is a rough port to Linux/EMC of 
the code Alan came up with for his pendant mixed with some
of the code from the jog sections of Xemc or Keystick

it uses the 4 button inputs of the game port only and handles the
encoder and two push buttons to set the axis and jog increment
and sends the same messages to EMC as the GUI would

I've tested parts of it and the encoder bit works fine with no
extra external logic on the encoder lines using a home built
encoder setup I hacked together just keep it simple and run
the A and B lines right into the game port
 
the idea is to build this as a standalone task module that can be
loaded alongside ANY of the existing user interfaces without
having to rewrite all of them to include this feature 
all of the current interfaces are already set to display the selected axis
and increment on each refresh so it dosent matter if the message 
came from the UI itself or another module
making it into a loadable module is the bit I'm still having trouble with

task timing
the handwheel task should only be active while in jog mode
and should be scheduled to run just fast enough to keep up
with the average Joe spinning the knob at a controlled rate
so maybe one hundred times per second max if the axis can even keep up 
at this ( max_jog_speed * max_jog_increment) combination
(the real world is SOOO much slower than the CPU world)

spinning the knob faster than this will cause some incremental jog commands
to be skipped over ,the axis will still move as fast as it can as long as
you are spinning but will stop on a multiple of the increment without
overshooting as soon as you quit turning the wheel

this would give it a nice ,predictable and fairly safe behavior 

Brian
//EMC handwheel jog module for the gameport

/*!
the game port pinouts for machine jog controls

power and ground ,two of these are commonly used for the MIDI port
check the docs on your port from the motherboard or soundcard manual
and break them out seperatly so the MIDI port is still available later on
pins 1,8,9,15 = +5V (both outermost pairs)
pins 4,5,12 = gnd (three in the center)

analog pins are not used
pin-3 = analog-1 = bit-0 of port 0x201
pin-6 = analog-2 = bit-1
pin-11 = analog-3 = bit-2
pin-13 = analog-4 = bit-3

the four digital pins on upper nibble are used
but must be shifted over and masked off in the code
these pins are normaly open (pulled up) the buttons should close to GND
pin-2 = digital-1 = bit-4                 axis select button
pin-7 = digital-2 = bit-5                 jog increment select button
pin-10 = digital-3 = bit-6               encoder ch-A
pin-14 = digital-4 = bit-7               encoder ch-B

the axis and jog increment selection buttons are used to scroll thru a list of values shown on
the screen by the GUI
the handwheel encoder is polled and compaired to its last value to test for step and direction
a CUI RE20NC25C20RA (Digi-Key Part Number 102-1012-ND) 25 line encoder would be
fine for this
note do not use the inexpensive detented encoders as they only have 25 detents
instead build the detents (100 of them) into the pannel knob and use the non-detented
25 line encoders

/*

        /*set the port address */
#define GAMEPORT 0x201

/*we need a function to read the port for Linux we can use this*/
get_joystatus(int port)
{
unsigned char ch;
ioperm(port,1,1);
ch=inb(port);
return ch;
}

//set up variables
unsigned char joystatus ,last_joystatus ,handwheel ,last_handwheel ,axis_btn ,incr_btn;

static double jogIncrement = 0.0001;
static double jogSpeed = 60.0;
static int axisSelected =0;

//=====================================================================
//activate in manual mode only
if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL)
{
/* first initialize joystatus and handwheel */
        {
        last_joystatus = get_joystatus(GAMEPORT);
        last_handwheel=(last_joystatus>>0x06) & 0x03 ;
        }

/*then in the jog loop*/

joystatus=(get_joystatus(GAMEPORT));
if (joystatus!= last_joystatus) /*something has changed*/
        {
        //set to jog incremental
        jogMode = JOG_INCREMENTAL;
        // get current values for increment and axis select buttons and handwheel state
        axis_btn=(joystatus>>0x04) & 0x01
        incr_btn=(joystatus>>0x05) & 0x01
        handwheel=(joystatus>>0x06) & 0x03
        }

// check the buttons first -button pressed=0 open=1
// and scroll thru values
if ( !axis_btn) {
                        axisSelected++
                        if (axisSelected < 0 || axisSelected >= EMCMOT_MAX_AXIS)
                                {
                                axisSelected=0;
                                }
                        }

if ( !incr_btn){
                        jogIncrement *= 10.0;
                        if (jogIncrement >= 0.1)
                                {
                                jogIncrement = 0.0001;
                                }
                        }


// test for handwheel change
if (handwheel != last_handwheel)
                {
                        switch (handwheel){
                                case 0x00:
                                        if(last_handwheel == 0x03)
                                        jogSpeed = jogSpeed;   /*fwd*/
                                        else if(last_handwheel == 0x01)
                                        jogSpeed = -jogSpeed;  /*rev*/
                                        else // should never get here
                                        jogSpeed=0.0;   /*error -do nothing*/
                                break;
                                case 0x01:
                                        if(last_handwheel == 0x00)
                                        jogSpeed = jogSpeed;
                                        else if(last_handwheel == 0x02)
                                        jogSpeed = -jogSpeed;
                                        else
                                        jogSpeed=0.0;
                                break;
                                case 0x02:
                                        if(last_handwheel == 0x01)
                                        jogSpeed = jogSpeed;
                                        else if(last_handwheel == 0x03)
                                        jogSpeed = -jogSpeed;
                                        else
                                        jogSpeed=0.0;
                                break;
                                case 0x03:
                                        if(last_handwheel == 0x02)
                                        jogSpeed = jogSpeed.;
                                        else if(last_handwheel == 0x00)
                                        jogSpeed = -jogSpeed;
                                        else
                                        jogSpeed=0.0;
                                break;
                                default :// should never get here
                                jogSpeed=0.0;
                                }
                        last_handwheel=handwheel; // store value for next time

       // pass the new values to EMC
        emc_axis_incr_jog_msg.serial_number = ++emcCommandSerialNumber;
        emc_axis_incr_jog_msg.axis = axisSelected;
        emc_axis_incr_jog_msg.vel =jogSpeed / 60.0;
        emc_axis_incr_jog_msg.incr =  jogIncrement;
        emcCommandBuffer->write(emc_axis_incr_jog_msg);
                }
}



Date Index | Thread Index | Back to archive index | Back to Mailing List Page

Problems or questions? Contact