Machsupport Forum
Mach Discussion => VB and the development of wizards => Topic started by: iceblu3710 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!
-
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
-
Thanks for the replay, you GetAsyncKeyState() suggestion works great. sofar I have:
'#################################
'# #
'# 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:
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:
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.
-
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.
-
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,
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.
-
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 (http://www.codeproject.com/KB/system/WindowsHookLib.aspx) I have edited the example so it only captures keyboard output but the best thing is its this simple:
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!!
-
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
-
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
-
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 (http://dl.dropbox.com/u/3586943/WindowsHookDemo.zip)
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?
-
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??
-
I started looking into this issue but found your zip file is no longer available. Thought id attempt to try to solve this through a plugin. Wanted to get an update on your progress. And any info that might be handy. Thanks for what you did post.
-
Hey,
Thanks for the interest. The project took a few different turns and is now a visual c++ plugin. However I did get it working and it will detect any button presses globally.
Theirs now alot to the plugin, most of it is the keyhook initialization in the main config form. I have not touched the file in many months, work sent me around town and back to school and I wont be able to take a crack at it again for a month or two more.
My goal was to add a feature to the keyhook library to consume keypresses and make a better config interface. Good luck!
http://www.4shared.com/file/bmJAjlgU/CustomPluginDLL.html? (http://www.4shared.com/file/bmJAjlgU/CustomPluginDLL.html?)