Hello Guest it is April 26, 2024, 10:52:40 AM

Author Topic: Detecting Button Presses  (Read 9381 times)

0 Members and 1 Guest are viewing this topic.

Detecting Button Presses
« on: December 21, 2009, 12:34:39 AM »
I want to write a script or brain that detects keyboard button states.

Specificly I have an encoder wired to my keyboard so that it produces quadrature of:
Down A, Down B, Up A, Up B and I would like to map this to mach so that I can use my keyboard encoder rig to jog.

Anybody have an idea how to even start this? I did not see any keyboard button abilities in the cypress pdf.

Thanks!

melee

*
Re: Detecting Button Presses
« Reply #1 on: December 22, 2009, 11:49:16 AM »
Hi,

See   http://www.machsupport.com/forum/index.php/topic,13038.0.html

In it I have shown a simple use for and prototyping of GetAsyncKeyState() from ../system32/user32.dll

You can use it to poll for key presses and then act upon those you want to trap.
Just be careful where you put your polling code and pass control back quickly, or the system will effectively hang waiting for key input.

If the keyboard strokes are being solely used by your routine, then you will probably need to remove them from the keyboard buffer too.
Plenty of documentation on the net re manipulating the keyboard buffer.

regards

Melee
Re: Detecting Button Presses
« Reply #2 on: December 22, 2009, 10:16:41 PM »
Thanks for the replay, you GetAsyncKeyState() suggestion works great. sofar I have:

Code: [Select]
'#################################
'#                               #
'#       Keyboard Encoder        #
'#       v0.0.1                  #
'#       Dec 22, 2009            #
'#                               #
'#################################

'---------- Includes ------------
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

'---------- Variables -----------
Const HaltKey = &H1B  'Esc
Const Enc_A = &H5A    'Z
Const Enc_B = &H58    'X

'---------- Main Function ------------
Sub Main()
 Message("") 'Clear The Message Space

 Do
  If HaltKeyPressed() = true Then
   Message "Macro Aborted!"
   Exit Do
  End If
  
  If A_Result() = true Then
   Message "A!"
  End If
  If B_Result() = true Then
   Message "B!"
  End If
  If A_Result() And B_Result() = true Then
   Message "A+B!"
  End If
  
  Sleep(100)
 Loop

End Sub
'--------------------------------------

'------------ Escape Routine ----------
Sub HaltKeyPressed()
 Dim Result As Boolean

 If GetAsyncKeyState(HaltKey) < 0 Then
  Result = true
 Else
  Result = false
 End If

 HaltKeyPressed = Result
End Sub
'--------------------------------------

'------------ Encoder Capture ---------
Sub A_Result()
 Dim Result As Boolean

 If GetAsyncKeyState(Enc_A) < 0 Then
  Result = true
 Else
  Result = false
 End If

 A_Result = Result
End Sub

Sub B_Result()
 Dim Result As Boolean

 If GetAsyncKeyState(Enc_B) < 0 Then
  Result = true
 Else
  Result = false
 End If

 B_Result = Result
End Sub
'-----------------------------------------

Just as a basic setup to make sure my encoder is outputting properly.

I have a modified keyboard map that shifts the encoder keys (not actually z or x) into unused virtual keys so not to interfere with normal keyboard operations.

Now I only need to figure out how to turn it all into a ++ or -- rotation so I can push some buttons.

------------- EDIT ---------------

I see GetKeyState() will give a 1 or 0 depending on key state and will not be cleared by another app polling the GetAsyncKeyState() function but for some reason the a-z/A-Z/0-9's all give a 1 no matter whats going on. I suck at VB and theirs no variable monitor in Mach so I have no idea what the returns are really doing. The MSDN database shows WM_KEYUP / WM_KEYDOWN Notification's but I have no idea how to use these either...

Once I figure out the key polling this is the general idea:

Code: [Select]
Dim Pos_Old As Integer
Dim Pos_New As Integer

Pos_New = GetKeyState(Enc_A)
Pos_New = (GetKeyState(Enc_B) << 1)

This will create a 2bit variable that I can do the following checks on:

Code: [Select]
if Pos_New = Pos_Old Then Exit
if Pos_New is one of these in a case statement:
0:1 ++
0:2 --
1:3 ++
1:0 --
3:2 ++
3:1 --
2:0 ++
2:3 --

Then simulate a button push in the right direction on whichever axis is selected.
« Last Edit: December 22, 2009, 11:17:40 PM by iceblu3710 »

melee

*
Re: Detecting Button Presses
« Reply #3 on: December 23, 2009, 05:11:41 AM »
Hi

I will be interested if you find a solution purely under VB.

Because Windows is application and window orientated, it attributes any keystrokes to the window with focus at the time so Application.DoEvents() will use them up, but could have unwanted side effects.

The only other methods I know of for system wide control is either direct access via assembler or C or using hooks.

The below link is a hooks library which works with VB, you might be able to call it from VBS OK as it appears just to be a .dll with an API which gives all the access you would need.

http://www.vbaccelerator.com/home/VB/Code/Libraries/Hooks/vbAccelerator_Hook_Library/article.asp

regards

Melee

PS.  There is a variable monitor, but not a variables list.
It requires that you assign returns to a variable, you cannot just run the mouse over the piece of code and see the result, as you can do in other programming setups

If you do

Dim retval As Double

retval = GetAsyncKeyState(0x20h)

in the VB Editor window and step through it, running the cursor across retval will show you what value it changed to.
« Last Edit: December 23, 2009, 12:02:23 PM by melee »
Re: Detecting Button Presses
« Reply #4 on: December 23, 2009, 09:01:44 PM »
Hey thanks for the info, I had never stepped through a script but now I know how to monitor variables.

I downloaded VBAccelerator but cannot make any sence of it and can VBS do . and -> function calls?? If so it should work If I could figure how how to declare functions from the bloody dll. Theirs not much documentation besides forum posts recommending it. Im sure a full featured VB editor would make more sence with it but thats still not very usefull for my application.

Have you ever used VBaccelerator before? If so could you give a simple example that say sets a variable to 1 if its key is depressed and 0 when released? OR heck even an example with the functions properly declared!

EDIT: If I do this,

Code: [Select]
Dim retval As Double

retval = GetAsyncKeyState(&HA0)

It always comes back as 0 no matter what (A0 is left shift). VBS does not support the standard hex line (0xA0h) am I doing it wrong or something? I find it hard sence my escape routine works just fine on just that key and its a &H1B

Thanks.
« Last Edit: December 23, 2009, 11:48:14 PM by iceblu3710 »
Re: Detecting Button Presses
« Reply #5 on: December 24, 2009, 08:48:36 AM »
Morning,

I wish I could just assign the output of me encoder directly to mach it would be a million times easier... im going to decode the output and turn it into CW and CCW keyboard presses then depending on which mpg axis led is lit activate the correct button for +/-. Its a long way to get there but ive found a dll that will do exactly what I want and its very neatly written.

Windows Hook Lib I have edited the example so it only captures keyboard output but the best thing is its this simple:

Code: [Select]
Me.KeyboardHook1.InstallHook()

Private Sub KeyboardHook1_KeyDown(ByVal sender As Object, ByVal e As WindowsHook.KeyboardEventArgs) Handles KeyboardHook1.KeyDown
'Do Stuff
End Sub 

Private Sub KeyboardHook1_KeyUp(ByVal sender As Object, ByVal e As WindowsHook.KeyboardEventArgs) Handles KeyboardHook1.KeyUp
'Do Stuff
End Sub

 Me.KeyboardHook1.RemoveHook()

I installed visual basic studio 2008 and am just going to write a little wrapper program to translate the encoder into cw/ccw as VBS just cannot handle the more complex system calls.

A0 is the virtual key for Left Shift, I use virtual keycodes for everything as my encoder and cw/ccw are in the unused key range so it wont interfere with program use.

I will post with a link to my project when I build it tonight, Have a great Christmas!!

Offline Chaoticone

*
  • *
  •  5,624 5,624
  • Precision Chaos
    • View Profile
Re: Detecting Button Presses
« Reply #6 on: December 24, 2009, 04:32:26 PM »
This is a most interesting topic to me. I have been wanting to know a way I could build buttons in VB that will jog on press and stop on release. The oem codes work well in vb but aren't intelligent enough to stop on release. I have always had to use the system functions for the jog buttons which work well and stop on release but if you want your buttons to do other things as well as jog you have been out of luck. I have not been able to figure out how to do that. Getting this working would be a huge help in screen design I think. You could have jog buttons that multi task. Could dictate which axis to use with mpg or jog the axis depending on the state of other things you can monitor.  Do you think your solution will fix/address this?

Merry Christmas,
Brett
;D If you could see the things I have in my head, you would be laughing too. ;D

My guard dog is not what you need to worry about!

melee

*
Re: Detecting Button Presses
« Reply #7 on: December 26, 2009, 11:21:04 AM »
Hi again

In parallel to your travails with the KeyboardHook libraries, I have tried to implement the user32.dll functions direct through VBS.

VBS was quite happy with the function declarations and I was able to rewrite the example code I found in a linear form, not using any forms or classes.

The stumbling point, was the inability to write the windows callback function, to implement the hook,  because there is no method of passing its address in the scripted language that I could find.
ie.  KeyboardHandle = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf KeyboardCallback,App.hInstance, 0&)

So I await your results to see if I can re-use any of it usefully for future macros.

regards

Melee
Re: Detecting Button Presses
« Reply #8 on: December 26, 2009, 03:16:47 PM »
Hello all, How was your Christmas? I think I took three naps and late last night I finished the MPG Translation part of my project!

I ended up using a different hook library and through the free visual basic studio 2008 download write a little app that translated my cw/ccw quadrature sequence into three buttons:

MPG Pulse        - VKF0
MPG CW          - VKF2
MPG CCW        - VKF4

My VB app traps the events from the encoder so no window is confused by hundreds of key presses a second when the MPG is being spun. Now I am working on the final VBS script to tie this into Mach3 like this:

I put two buttons on the screen labled MPG CW and MPG CCW and assigned them the shortcut keys VKF2 and VKF4 then wrote a little if block like this:

If getORMLED(59) Then   'If X Axis Selected
  doOEMButton(307) 'X+
End IF

But then I realized that while mach is in MPG control the standard jog buttons do not work anymore. So to test I removed the if and just kept the doOEMButton(307) and the same for the CCW button. Now I see what Chaoticone is talking about not stopping on release! If I move my MPG it will just move the axis untill it trips a limit or I estop... So now that I understand what Chaoticone is talking about Ive got some ideas on how to fix it.

In the meantime feel free to check out my 'code' below, I say code lightly as its about 8 if statements and thats it lol

----------------------------------------
Here Is my VB Studio Project

EDIT:

I am thinking if making my own jog screen that I will have my X/Y/Z/A DRO's as well as a DRO for a MPG jog step size and axis selection. Sence I cannot jog in Mach's standard MPG mode im just going to make my own little version that accepts keyboard inputs instead.

Does anyone have any recommendations on what choices you find invaluable in MPG mode?
« Last Edit: December 26, 2009, 03:46:58 PM by iceblu3710 »
Re: Detecting Button Presses
« Reply #9 on: December 26, 2009, 05:03:52 PM »
Ok so I have discovered that macros are VERY SLOW and do not facilitate handling the input from an MPG. When I spun my encoder fast enough it would either miss steps or skit just enough to think it was going the other way. I have watched the Brains tutorial videos but do not find the system intutive AT ALL and the fact that I cant go back a few rungs and add something means I have re-written my program several times and none of them worked anyways.

I also dislike the fact that brains do not have the ability to have buttons as inputs. I assume you just assign a button to toggle an led then use the led to trigger the brains but how do you toggle an led with a button? The only way I know is via a macro and then its back to being slow again...

Is this the only way to get a button press into the brains or is their something I am missing??