Skip to main content

In this application, the GalilTools COM library is used in conjunction with Microsoft Visual Basic 2010 to develop a user interface for the Galil controller. The goal is to create a simple interface that features both directional buttons for mouse interaction and the ability to poll for keyboard input. Using this digital stimulus, the application is to act similar to an analog joystick control interface. The completed user interface is visible below.

 

   

 

To ensure smooth control, the states of all relevant directional inputs are recorded. A similar prototype is used for commanding motion regardless of the input interface method. This creates a consistent feel between the mouse activated buttons and direct keyboard input.

On a 50 millisecond time pitch, the state of the inputs is processed. The result is an increase or decrease in the relevant velocity vector variable. The velocity increase/decrease magnitudes are book kept as the acceleration variables. If the user continuously commands a directional input, the corresponding axis velocity will be adjusted until the saturation condition is met, where the velocity magnitude is greater than the axis' velocity_MAX variable.

In the event that no directional input has been given for an axis of motion, on the 50 millisecond time pitch, the axis velocity vector is adjusted by the deceleration variable to get closer to zero. This effectively linearly slows the motion to a stop, similar to how friction could slow a moving object.

The final task of the repetitive time pitch subroutine is to send a velocity command to the motion controller. This is easily executed using the GalilTools COM library's “command” functionality. An XY Jog is initiated using the command “JG VX,VY” where VX and VY are the X and Y axis velocity vectors, accordingly.

The final features of the application are the “Begin XY Jog” “Stop XY Jog” buttons. The begin button will perform a servo here command and begin motion command for the X and Y axises, effectively enabling motion on the axis. The stop button performs a stop command for the X and Y axises, effectively hauling motion. If the velocity vectors have values in the application but there is not motion, ensure that the “Begin XY Jog” button has been clicked.

The outcome is the creation of a user interface that allows for users to command two axis motion using either keyboard or button based mouse input. Simple physics are incorporated into the application to ensure smooth motion and control. The source listing is approximately 180 lines and is available below. Alternatively the entire project source can be downloaded at this link.

PublicClassmainForm

  'Define an array with booleans for each key

  Dim Keys(255) AsBoolean

 

  'Define a structure with all relevant axis components

  PublicStructureaxis_componets

    Public velocity AsInteger

    Public velocity_MAX AsInteger

    Public acceleration AsInteger

    Public deceleration AsInteger

  EndStructure

 

  'Initialize axis components for X and Y

  Public X AsNewaxis_componets

  Public Y AsNewaxis_componets

 

  'Establish controller handle

  WithEvents g AsNew Galil.Galil

 

  'Define Keycodes for directional keys

  EnumKeyCodes

    left = 37

    right = 39

    up = 38

    down = 40

  EndEnum

 

  PrivateSub mainForm_Load() HandlesMyBase.Load

    'Connect the controller

    'g.address = "10.0.5.72"

    g.address = ""

    Me.Text = g.connection

 

    'Initialize Motion Parameters for X and Y

    X.velocity = 0

    Y.velocity = 0

    X.velocity_MAX = 10000

    Y.velocity_MAX = 10000

    X.acceleration = 400

    Y.acceleration = 400

    X.deceleration = 800

    Y.deceleration = 800

 

    'Rotate arrow icons to correct orientation

    down_arrow.Image.RotateFlip(RotateFlipType.Rotate180FlipNone)

    right_arrow.Image.RotateFlip(RotateFlipType.Rotate90FlipNone)

    left_arrow.Image.RotateFlip(RotateFlipType.Rotate270FlipNone)

 

    'Start The Timer Up

    Timer1.Start()

  EndSub

 

  'This allows arrow key presses when focus on stop_jog button

  'Intercepts default move to other button

  PrivateSub stop_jog_PreviewKeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles stop_jog.PreviewKeyDown

    SelectCase (e.KeyCode)

      CaseKeyCodes.left, KeyCodes.right, KeyCodes.up, KeyCodes.down

        e.IsInputKey = True

    EndSelect

  EndSub

  'This allows arrow key presses when focus on begin_jog button

  'Intercepts default move to other button

  PrivateSub begin_jog_PreviewKeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles begin_jog.PreviewKeyDown

    SelectCase (e.KeyCode)

      CaseKeyCodes.left, KeyCodes.right, KeyCodes.up, KeyCodes.down

        e.IsInputKey = True

    EndSelect

  EndSub

 

  'If key is pressed then set the corresponding boolean of the index in the key array to true

  PrivateSub mainForm_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) HandlesMyBase.KeyDown

    Keys(e.KeyValue) = True

  EndSub

  PrivateSub mainForm_KeyUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) HandlesMyBase.KeyUp

    Keys(e.KeyValue) = False

  EndSub

 

  'Begin Jog Button Action

  PrivateSub begin_jog_Click() Handles begin_jog.Click

    'Connect server and start motion

    g.command("SH XY")

    g.command("BG XY")

  EndSub

 

  'Stop Jog Button Action

  PrivateSub stop_jog_Click() Handles stop_jog.Click

    g.command("ST XY")

  EndSub

 

  'If form arrow image is clicked on then set the index in the key array to true

  PrivateSub up_arrow_MouseDown() Handles up_arrow.MouseDown

    Keys(KeyCodes.up) = True

  EndSub

  PrivateSub down_arrow_MouseDown() Handles down_arrow.MouseDown

    Keys(KeyCodes.down) = True

  EndSub

  PrivateSub left_arrow_MouseDown() Handles left_arrow.MouseDown

    Keys(KeyCodes.left) = True

  EndSub

  PrivateSub right_arrow_MouseDown() Handles right_arrow.MouseDown

    Keys(KeyCodes.right) = True

  EndSub

 

  'If form arrow image click is released then set the index in the key array to false

  PrivateSub up_arrow_MouseUp() Handles up_arrow.MouseUp

    Keys(KeyCodes.up) = False

  EndSub

  PrivateSub down_arrow_MouseUp() Handles down_arrow.MouseUp

    Keys(KeyCodes.down) = False

  EndSub

  PrivateSub left_arrow_MouseUp() Handles left_arrow.MouseUp

    Keys(KeyCodes.left) = False

  EndSub

  PrivateSub right_arrow_MouseUp() Handles right_arrow.MouseUp

    Keys(KeyCodes.right) = False

  EndSub

 

  'Every timer tick of the clock update the velocity vector and send motion command

  PrivateSub Timer1_Tick() Handles Timer1.Tick

    'My.Application.Log.WriteEntry(X.velocity.ToString + " " + X.velocity_MAX.ToString)

 

    'Check the Limits and process command X

    If (System.Math.Abs(X.velocity) < X.velocity_MAX) Then

      'If left or right direction then accelerate the Y axis

      If Keys(KeyCodes.right) Then'Right

        X.velocity += X.acceleration

      EndIf

      If Keys(KeyCodes.left) Then'Left

        X.velocity -= X.acceleration

      EndIf

    EndIf

 

    'Check the Limits and process command Y

    If (System.Math.Abs(Y.velocity) < Y.velocity_MAX) Then

      'If up or down direction then accelerate the Y axis

      If Keys(KeyCodes.up) Then'UP

        Y.velocity += Y.acceleration

      EndIf

      If Keys(KeyCodes.down) Then'Down

        Y.velocity -= Y.acceleration

      EndIf

    EndIf

 

    'If there is no directional input then decelerate

    If (Keys(KeyCodes.left) + Keys(KeyCodes.right) = 0) Then

      'Reduce speeds to zero if under decelleration threshold

      'necessary when deceleration is not a multiple of acceleration

      If (System.Math.Abs(X.velocity) < X.deceleration) Then

        X.velocity = 0

      EndIf

 

      'Decelerate the X

      If X.velocity > 0 Then

        X.velocity -= X.deceleration

      ElseIf X.velocity < 0 Then

        X.velocity += X.deceleration

      EndIf

    EndIf

    If (Keys(KeyCodes.up) + Keys(KeyCodes.down) = 0) Then

      'Reduce speeds to zero if under decelleration threshold

      'necessary when deceleration is not a multiple of acceleration

      If (System.Math.Abs(Y.velocity) < Y.deceleration) Then

        Y.velocity = 0

      EndIf

 

      'Decelerate the Y

      If Y.velocity > 0 Then

        Y.velocity -= Y.deceleration

      ElseIf Y.velocity < 0 Then

        Y.velocity += Y.deceleration

      EndIf

    EndIf

 

    'Update velocity output displays

    X_velocity_display.Text = X.velocity.ToString()

    Y_velocity_display.Text = Y.velocity.ToString()

 

    'Send the velocity commands

    g.command("JG " + X.velocity.ToString + "," + Y.velocity.ToString)

    'My.Application.Log.WriteEntry("JG " + X.velocity.ToString + "," + Y_velocity.ToString)

  EndSub

EndClass