Second keyboard/mouse for a machine I built running Mach 3 on Win 7

Status
Not open for further replies.
I have three known locations on a display monitor (Mach3 CNC controller) that I want to be able to press a button at a different location than that of the display, keyboard and mouse to indicate that I want the action at that location to be acted upon. Two of these actions are to set the Mach 3 controllers axis position to zero. The third will be to tell the controller to test for the Z axis zero position which will run a script macro to accomplish that.
These are pretty straight forward mouse move to absolute positions and right click once there. Although, I am not sure about absolute positioning of the mouse as somewhere I read that the mouse movements were all relative to its current position.
That requires 3 momentary inputs.
The final need is to again operate momentary inputs (6) to output the following keyboard characters:
KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_PAGEUP, KEY_PAGEDOWN.
All of these key presses may be momentary or repeated by holding down the switch, their purpose is to cause the movement of an axis as needed for fine positioning.
This box will be a second keyboard/mouse with these functions. I purchased the Teensy 3.2 to accomplish this task and researched the different possible libraries. I am new to this and have not done any significant engineering or even programming in maybe 30 years, so am at a loss as to exactly what some things mean. I read that Paul redid the library for the 3.2 from the 2.0. I downloaded the Teensyduino libraries and installed them, but cannot find the USB_Keyboard library to include. I think I am just confused due to my lack of experience.
If someone could point me in the right direction, I would very much appreciate the assistance.

I used a numeric keypad recently on the machine (I built the CNC machine from plans) and it had some drawbacks, one was it seemed that the num lock would always be the opposite the main keypad on the keyboard and I always had to push it and when I returned to the main keyboard, I had to push it as well. I am not going to use num lock, instead input those keypresses as indicated above. Should eliminate that problem, I hope. Secondly, the keypad did not have the additional 3 abilities as indicated in the first paragraph of mouse moves and right clicks.
Lastly, as a 70-year-old geezer, it is a new challenge that will be a joy to complete.
Thank you,

woodcrafter USB Logic for Direction Control and Axis  Zeroing - Page 1.jpg
 
Last edited:
If I understand all the technical stuff, the teensy 3.2 actually connects to the PC as a USB Keyboard and Mouse if that mode is selected, and therefore I can just write code to read inputs and determine what outputs may be necessary.
 
That's pretty much it, if you have not already installing Arduino, Teensyduino and having a look at the keyboard examples is probably where you want to be. Limits here are:
How far away you can be from the PC and still get USB to work
Since it is just a keyboard there is no feedback - if a popup happens on screen your keypresses go to the wrong program

If the first is a problem then you can run the keypad on a longer wire, or even use a teensy pair to get a longer distance
For the second how much this matters depends on if you can see the screen etc from the control location - full solution would be to use serial into Mach-3 but that would be a lot more work.

edit - mach 3 docs do not seem to mention serial jog control as an option but do support joystick (or more normally gamepad) input so this may actually give you more control, at the cost of more complex code and hardware to support the wider range of options.
 
Last edited:
In Arduino, click File > Examples > Teensy > USB_Keyboard > Buttons for an example which should get you started.

You'll probably want to change the code from Keyboard.print() to Keyboard.press() and Keyboard.release(), for the specific keys you wanted. Details here: (scroll down to "Individual Key Press / Release")

https://www.pjrc.com/teensy/td_keyboard.html

But first I highly recommend just running the example and touch a wire or paperclip between GND and the nearby pins, if you don't have buttons wired up. The best way to get started on this sort of project is from a working example. :)

Even if you don't go with that example, I highly recommend using the Bounce library (as shown in that example) to read the buttons. You can use digitalRead to directly access the pins, but Bounce handles the mechanical chatter of the buttons for you. If you want to get things working easily, Bounce will save you a lot of time & frustration.
 
Thank you, both for the responses. I will follow your advice. I will keep you informed as to my successes, again thank you.
 
I followed your advice and used the USB_Keyboard example. That worked fine, I added the LED blink routine to show me that the program actually downloaded and started. as I was not running the MACH 3 in this 0 degree weather in my shop. I changed to Keyboard.press for outputting the keyboard characters that I needed to emulate and then added the USB mouse commands to move and set the mouse per predetermined locations on the screen. It appears that when I keep a button down, that I get repetitive output which was a concern as these the keyboard outputs represent jog requests. Until I can get to the machine and test, I won't know exactly how this will fly.

Again thank you for pointing me in the right direction
 
I haven't tested this yet as it is still very cold in my workshop where my CNC machine is located, but I am wondering about timing for mouse moves and mouse clicks. my code is:
if (button6.fallingEdge()) {
digitalWrite(21, HIGH);
Mouse.moveTo(1290, 118);
delay(150);
Mouse.set_buttons(1, 0, 0);
delay(500);
Mouse.set_buttons(0, 0, 0);

I assumed that I need some time to allow the mouse to move, but I am not sure that is true, I also assumed to hold the button down some finite time for the click to take effect, not sure that is true either. This is one of three mouse moves and left clicks that would be instigated by a button push away from the location of the mouse and keyboard with known screen locations.
The entire program follows:

int count = 0;
#include <Bounce.h>
// Create Bounce objects for each button. The Bounce object
// automatically deals with contact chatter or "bounce", and
// it makes detecting changes very simple.

Bounce button0 = Bounce(0, 10);
Bounce button1 = Bounce(1, 10); // 10 = 10 ms debounce time
Bounce button2 = Bounce(2, 10); // which is appropriate for
Bounce button3 = Bounce(3, 10); // most mechanical pushbuttons
Bounce button4 = Bounce(4, 10);
Bounce button5 = Bounce(5, 10); // if a button is too "sensitive"
Bounce button6 = Bounce(6, 10); // to rapid touch, you can
Bounce button7 = Bounce(7, 10); // increase this time.
Bounce button8 = Bounce(8, 10);
void setup() {
// Configure the pins for input mode with pullup resistors.
// The pushbuttons connect from each pin to ground. When
// the button is pressed, the pin reads LOW because the button
// shorts it to ground. When released, the pin reads HIGH
// because the pullup resistor connects to +5 volts inside
// the chip. LOW for "on", and HIGH for "off" may seem
// backwards, but using the on-chip pullup resistors is very
// convenient. The scheme is called "active low", and it's
// very commonly used in electronics... so much that the chip
// has built-in pullup resistors!

Mouse.screenSize(1680, 1050); // configure screen size My CNC Machine
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP); // X zero
pinMode(7, INPUT_PULLUP); // Y zero
pinMode(8, INPUT_PULLUP); // ZED zero select
pinMode(15, OUTPUT); // LED Indicators for switch pressed Clear
pinMode(16, OUTPUT); // LED Indicators for switch pressed Clear
pinMode(17, OUTPUT); // LED Indicators for switch pressed Yellow
pinMode(18, OUTPUT); // LED Indicators for switch pressed Yellow
pinMode(19, OUTPUT); // LED Indicators for switch pressed Blue
pinMode(20, OUTPUT); // LED Indicators for switch pressed Blue
pinMode(21, OUTPUT); // LED Indicators for switch pressed Red
pinMode(22, OUTPUT); // LED Indicators for switch pressed Red
pinMode(23, OUTPUT); // LED Indicators for switch pressed Red
}

void loop() {
// Update all the buttons. There should not be any long
// delays in loop(), so this runs repetitively at a rate
// faster than the buttons could be pressed and released.

button0.update();
button1.update();
button2.update();
button3.update();
button4.update();
button5.update();
button6.update();
button7.update();
button8.update();

// Check each button for "falling" edge.
// Indicated key press on the Keyboard when each button presses
// or mouse move and click for button 6 through 8
// falling = high (not pressed - voltage from pullup resistor)
// to low (pressed - button connects pin to ground)

if (button0.fallingEdge()) {
Keyboard.press(KEY_UP);
digitalWrite(15, HIGH);
}
if (button1.fallingEdge()) {
Keyboard.press(KEY_DOWN);
digitalWrite(16, HIGH);
}
if (button2.fallingEdge()) {
Keyboard.press(KEY_LEFT);
digitalWrite(17, HIGH);
}
if (button3.fallingEdge()) {
Keyboard.press(KEY_RIGHT);
digitalWrite(18, HIGH);
}
if (button4.fallingEdge()) {
Keyboard.press(KEY_PAGE_UP);
digitalWrite(19, HIGH);
}
if (button5.fallingEdge()) {
Keyboard.press(KEY_PAGE_DOWN);
digitalWrite(20, HIGH);
}
if (button6.fallingEdge()) {
digitalWrite(21, HIGH);
Mouse.moveTo(1290, 118);
delay(150);
Mouse.set_buttons(1, 0, 0);
delay(500);
Mouse.set_buttons(0, 0, 0);
}
if (button7.fallingEdge()) {
digitalWrite(22, HIGH);
Mouse.moveTo(1290, 159);
delay(150);
Mouse.set_buttons(1, 0, 0);
delay(500);
Mouse.set_buttons(0, 0, 0);
}
if (button8.fallingEdge()) {
digitalWrite(23, HIGH);
Mouse.moveTo(375, 57);
delay(150);
Mouse.set_buttons(1, 0, 0);
delay(500);
Mouse.set_buttons(0, 0, 0);
}

// Check each button for "rising" edge
// Type a message on the Keyboard when each button releases.
// For many types of projects, you only care when the button
// is pressed and the release isn't needed.
// rising = low (pressed - button connects pin to ground)
// to high (not pressed - voltage from pullup resistor)

if (button0.risingEdge()) {
digitalWrite(15, LOW);
}
if (button1.risingEdge()) {
digitalWrite(16, LOW);
}
if (button2.risingEdge()) {
digitalWrite(17, LOW);
}
if (button3.risingEdge()) {
digitalWrite(18, LOW);
}
if (button4.risingEdge()) {
digitalWrite(19, LOW);
}
if (button5.risingEdge()) {
digitalWrite(20, LOW);
}
if (button6.risingEdge()) {
digitalWrite(21, LOW);
}
if (button7.risingEdge()) {
digitalWrite(22, LOW);
}
if (button8.risingEdge()) {
digitalWrite(23, LOW);
}
}
 
Thank you for the input, everything worked as it should, a minor quirk in the setting Z zero routine, but nothing major. My final sketch is a bit different than that above, mainly just cleaned up and adding a Keyboard.release() for each of the keyboards keys used added it to each of the if(buttonX.risingEdge()) conditions, maybe I didn't need it but felt better to be safe than have to add it later. Moving the mouse and then having a button press worked great. I kept the delays again, just to be safe. Someday I may take them out but each of these actions are manual processes and timing is not really critical with the exception that when I release a button I want the axis to stop moving at least as quickly as if I had released the equivilent button on the actual keyboard, which it appears to be true.
I learned a lot on this project and have some additional ideas I will be toying with in the future. My USB cable is a standard perhaps 3-foot long cable so I do not think distance is a concern. My PC is directly under the CNC machine so there are no long runs of cables.

Any thoughts on your part would be appreciated.
 
Last edited:
I have a follow-up question concerning the mouse. First of all, I am pleased with the code as it works very well, however, I must set the screen limits ie. Mouse.screenSize(1680, 1050); // configure screen size My CNC Machine. Later for 3 of the buttons I have code similar to this: if (button6.fallingEdge()) {
digitalWrite(21, HIGH);
Mouse.moveTo(1290, 118);
delay(150);
Mouse.set_buttons(1, 0, 0);
delay(500);
Mouse.set_buttons(0, 0, 0);

Not sure if I need the delays, but these are manual processes where I used to use the mouse so the delay does not impede anything. As you can see I have fixed x,y coordinates for this example and the other two also have fixed x, y coordinates. I am trying to make this work with any screen size without someone having to enter the parameters. The Questions:
1.) Is there a way to read the screen size? I was thinking of adding a "Set Button" and when it was pressed with another "set size button" would determine the resolution of the screen. 2.) using the same "Set Button" being pressed (with the mouse already moved to each of the three other functions one at a time, for the mouse above, such as at the Zero X position, pressing the Set Button and the Zero X button together would set the location of the screen button for X Zero, same actions for Y and the Z zeroing routine.
Being able to do this would make this a universal pendant for the Mach 3 and 4, and very inexpensive. Of course, I could set up different resolutions and determine the locations manually and just have a selector in the program to select which resolution was being used, that won't accomodate the 2010 version of the larger screen vs the standard Mach 3 however.
Thank you for any input you may have.
 
Status
Not open for further replies.
Back
Top