Raspberry Pi Pico Space Mouse for OnShape CAD Design
2023-02-22 | By Travis Foss
License: See Original Project Raspberry Pi MCU
For as long as I have worked in CAD programs, Iβve always thought it would be nice to have a βspace mouse to control certain aspects of the software. If you arenβt familiar, a space mouse is βa specialty mouse used to rotate or control a 3D object in a CAD Program. While looking into βsome of the DIY space mouse builds out there, I noticed that a lot of them are just using βAdafruitβs HID library to control some of the CAD commands, and it got me thinking of a βproject. Could I build a CAD Keypad?β
I was looking through the various products I had collected that were not in use yet and realized I βhad one of Pimoroniβs Pico RGB keypads (DK part number 1778-PIM551-ND). The Pimoroni Pico βRGB keypad uses a Raspberry Pi Pico for the microcontroller, one of the most readily available βmicrocontrollers. So, this would be a perfect project to learn more about the Pico and the Pico βRGB keypad.β
With OnShape being my most frequently used CAD software, I started researching what βkeyboard shortcuts exist for it. During my research, I discovered over 100 keyboard shortcuts βthat can be used with this software. There are so many shortcuts that they have them divided βinto different sections depending on what part of the program you are in. There is a general βsection, assembly section, part studio section, 3D view section, sketch section, and a drawings βsection.β
To test if my idea would work, I wanted to see if I could get the rotation of the object to work βfirst. In order to get that to work, I would need to be able to send the 4 keyboard directional βbutton commands to the software. After looking at the keypad, I decided to assign the button βlabeled 1 as the up arrow, 4 as the left arrow, 6 as the right arrow, and 9 as the down arrow.β
The next thing that I had to decide was whether I wanted to program these with either the βArduino IDE or CircuitPython. Since I had rarely used CircuitPython, I thought this might be a βgood learning experience to program with it.
βI started by downloading the latest version of CircuitPython for the Keybow 2040 as directed by βPimoroni in this getting started guide, https://github.com/pimoroni/pmk-circuitpython. Once βthat was completed my Pico RGB Keypad was showing up as a CircuitPython device on the βcomputer, so I knew I was ready to start programming it. I had previously used Thonny as the βIDE for programming so that was already installed on my computer.β
I then began to research what libraries were needed to get this up and running. While looking βthrough various projects other people had created, I noticed that there are a few commonly βused libraries. They are time, board, busio, and usb_hid. To get the LEDs on the board to work, I βalso had to add the Adafruit_dotstar library. Lastly, to add the capability for the device to βemulate keyboard functions, I Imported 3 libraries, Adafruit_hid.keyboard, βAdafruit_hid.keyboard_layout_us, and Adafruit_hid.keycode.β
import time import board import busio import usb_hid from adafruit_bus_device.i2c_device import I2CDevice import adafruit_dotstar from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS from adafruit_hid.keycode import Keycode
From there I dug into the code in Adafruitβs Keycode library, βhttps://docs.circuitpython.org/projects/hid/en/latest/, to determine which codes were used to βcall out the directional buttons. The commands were fairly straightforward as the up and down βdirectional arrows were called out by sending a keyboard command of Keycode.UP_ARROW βand Keycode.DOWN_ARROW and left and right were Keycode.LEFT_ARROW and βKeycode.RIGHT_ARROW. I opened Thonny and started putting together the program.β
After modifying the code, I had found from a couple of different sources, I ended up with the βfollowing code.
import time
import board
import busio
import usb_hid
from adafruit_bus_device.i2c_device import I2CDevice
import adafruit_dotstar
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode
from digitalio import DigitalInOut, Direction, Pull
cs = DigitalInOut(board.GP17)β
cs.direction = Direction.OUTPUT
cs.value = 0β
num_pixels = 16β
pixels = adafruit_dotstar.DotStar(board.GP18, board.GP19, num_pixels, brightness=0.1, βauto_write=True)β
i2c = busio.I2C(board.GP5, board.GP4)β
device = I2CDevice(i2c, 0x20)β
kbd = Keyboard(usb_hid.devices)β
layout = KeyboardLayoutUS(kbd)β
def read_button_states(x, y):β
β pressed = [0] * 16β
β with device:β
β device.write(bytes([0x0]))β
β result = bytearray(2)β
β device.readinto(result)β
β b = result[0] | result[1] << 8β
β for i in range(x, y):β
β if not (1 << i) & b:β
β pressed[i] = 1β
β else:β
β pressed[i] = 0β
β return pressed
held = [0] * 16β
while True:β
β pressed = read_button_states(0, 16)β
β β
β if pressed[1]: #check to see if button 1 is pressed
β β
β if not held[1]:#check to make sure the held variable isn't true
β print("Up Arrow") #print action to serial monitor
β kbd.send(Keycode.UP_ARROW)#send the keyboard command Up arrow to the device
β held[1] = 1β
β elif pressed[4]: #check to see if button 4 is pressed
β if not held[4]: #check to make sure the held variable isn't true β
β print("Left Arrow") #print action to serial monitor
β kbd.send(Keycode.LEFT_ARROW)#send the keyboard command Left Arrrow to the device
β held[4] = 1β
β β
β β
β elif pressed[6]: #check to see if button 6 is pressed β
β if not held[6]: #check to make sure the held variable isn't true
β print("Right Arrow") #print action to serial monitor
β kbd.send(Keycode.RIGHT_ARROW)#send the keyboard command Right Arrrow to the device
β held[6] = 1β
β elif pressed[9]: #check to see if button 9 is pressed
β if not held[9]:#check to make sure the held variable isn't true
β print("Down Arrow") #print action to serial monitor
β kbd.send(Keycode.DOWN_ARROW)#send the keyboard command Down Arrow to the device
β held[9] = 1β
β else: # Released state
β for i in range(16):β
β held[i] = 0 # Set held states to off
β time.sleep(0.1) # DebounceβIt was time to test to see if this would work as anticipated.
βFor the initial test, I pressed the βRun Current Scriptβ button in Thonny and started pressing the βassigned keypad buttons. I was getting the printouts of each of the directional keys in the Serial βmonitor, and it was also moving my cursor around in the code. Next up was to open an instance βof OnShape and test it in that environment. Once the software was open and one of my βdrawings active, I tried out the keypad by pushing the 4 buttons. It was rotating the object. It βwas working! The one thing that I did notice was that it was only rotating 15 degrees at a time, βand it wouldnβt rotate further unless I released and pressed the button again. β
Based on the initial test, I decided the next three things I would tackle would be adding color to βthe 4 buttons to keep track of which ones I was using, getting the continuous rotation working, βand adding an option so I could pan the object around the screen instead of rotating.β
Adding the color to the 4 buttons was fairly easy. To standardize the color, I wanted to create a βvariable (green) and assign it the RGB color code of 0,255,0. One thing I found out after βsearching the web to find out more about variables is that when declaring a variable, it does βnot need to be called out as a certain type of variable. Once the initial value is assigned, it is βautomatically classified behind the scenes. This makes creating variables simple. After creating βthe variable and assigning the values, I assigned them to the pixels for the four buttons that we βwere using - 1, 4, 6, and 9.β
The variable I created looked like this.β
green = (0,255,0)β
βUnder the while true statement, I also added these lines to get the pixels to light:
β#Color coding the buttons according to thier functionβ β pixels[1] = green β pixels[4] = green β pixels[6] = green β pixels[9] = green
I tested this by saving the code which automatically updates it on the board. The 4 buttons were βnow lit in green.ββ
if pressed[1]: #check to see if button 1 is pressed β
β if not held[1]:#check to make sure the held variable isn't true
β print("Up Arrow") #print action to serial monitor
β kbd.send(Keycode.UP_ARROW)#send the keyboard command Up arrow to the device
β held[1] = 1β
β elif pressed[4]: #check to see if button 4 is pressed
β if not held[4]: #check to make sure the held variable isn't true β
β print("Left Arrow") #print action to serial monitor
β kbd.send(Keycode.LEFT_ARROW)#send the keyboard command Left Arrrow to the device
β held[4] = 1βNext up was to try getting a constant rotation while the button was held. Looking deeper into βthe code (shown above), I noticed after the βif or elif pressedβ statements, there was an "If not βheldβ statement. Also, at the end of that statement, there was a variable called βheldβ that was βbeing changed to a β1β. My first thought was to comment out both the βif not heldβ statement, βas well as the βheldβ variable assignment for each of the buttons. Here is an example of what βthe code looked like for each button.
if pressed[1]: #check to see if button 1 is pressed
β# if not held[1]:#check to make sure the held variable isn't true
β print("Up Arrow") #print action to serial monitor
β kbd.send(Keycode.UP_ARROW)#send the keyboard command Up arrow to the device
β# held[1] = 1βI then saved the code and opened OnShape to see if this would work. I switched my screen to βOnShape, pressed the right directional button, and held it down. My drawing rotated βcontinuously. However, it was too fast to accurately control where I wanted the object to stop. I βthought for a few moments and began to wonder, what would happen if I added a slight delay βto the code. Will that slow it down at all? I entered a sleep command of 0.1 seconds or 100 βmilliseconds. I saved the code and uploaded it again.ββ
if pressed[1]: #check to see if button 1 is pressed
β# if not held[1]:#check to make sure the held variable isn't trueβ
β if pan != 1:β
β print("Up Arrow") #print action to serial monitor
β kbd.send(Keycode.UP_ARROW)#send the keyboard command Up arrow to the device
β time.sleep(0.1)β
β# held[1] = 1βThis time the part was continuously rotating but at a much more manageable speed.
βThe next step that I was looking to add was a Pan function for the controls. I knew I wanted to βtoggle this on and off without holding down a button. My first thought was to set up a variable. I βcalled it "pan" to be able to change back and forth between a 0 and 1 or true and false. Next, I βdecided to add a color to the button that would change depending on if the pan variable was βtrue or not. I decided that I would set the pixel to a light red color if the pan variable was false βand to orange if the pan variable was true. I then added code to change the variable to the βopposite condition when pushed, essentially setting it up similarly to a switch. Next, I went into βeach of the code sections for the 4 directional buttons and updated the code. So, there were βtwo conditions used, one for when the pan variable is false and one for when it is true. The βcurrent code I had up to this point was put under the βif pan does not equal 1β set of code. βUnder the βif pan does equal 1β set I updated the keyboard send command to include 3 βcommands, Keycode.CONTROL, Keycode.SHIFT, and the command for the directional arrow I βwas using such as Keycode.UP_ARROW. This would cause the object that I am looking at in βOnShape to pan in whichever direction Iβm pressing instead of rotating. Here is an example of βthat code.ββ
elif pressed[5]: #check to see if button 5 is pressed
β β
β if not held[5]:#check to make sure the held variable isn't true β
β if pan != 1: # check to see if the pan variable is not equal to 1β
β pixels[5] = light_red #set the pixel to light red
β pan = 1 #set the pan variable to 1β
β print("Control Shift ON") #print action to serial monitor
β held[5] = 1 #change the held variable for this button to true
β β
β elif pan == 1: # if the pan variable is equal to 1β
β pixels[5] = orange #set the pixel to orange
β pan = 0 #set the pan variable to 0β
β print("Control Shift OFF") #print action to serial monitor
β held[5] = 1 #change the held variable for this button to trueNext, I saved the code and went back to OnShape. I pressed button 5 and noticed the color on βthe key had changed. I then pressed the up button, and the object panned upwards. I then tried βpanning down while holding the button. It did pan downwards continuously however, there was βa slight delay after every step. To correct this, I tried commenting out the delay that I had βadded for the rotation commands. After updating the code, I saved it and went back to OnShape βagain. This time when I activated the pan button and held a directional button the object βpanned perfectly with no delay and not overly fast.β
Perfect!!
βThe commands to this point were all working out well so, I thought the next thing I could add βwas zoom functionality.
βLooking through the keyboard shortcuts available, I noticed that there were 4 options that I βthought would be good to include, Zoom in, Zoom out, Zoom to fit, and Zoom to Window. Next, βI decided that the next 4 buttons I would use were the ones labeled 0, 2, 8, and A. I decided to βuse button 0 as Zoom In, button 2 as Zoom out, button 8 as Zoom to Fit, and button A as Zoom βto Window. I also decided to set these buttons to a white color to differentiate them from the βother buttons used so far. After choosing these buttons, I proceeded to add the commands. The βcommand for Zoom In is SHIFT Z, for Zoom Out it is Z, for Zoom to Fit it is F, and Zoom to βWindow is W. Once these were all coded in and the code saved, I opened OnShape once again βto test the functionality. All worked as expected. I hadnβt used the zoom to window command βmuch before however adding it to the keypad I am finding myself using it more often all the βtime. Essentially zoom to window allows the user to draw a box around the section of the object βthey are working on, and it will zoom into that area.β
Example of the Zoom in code:ββ
if pressed[0]: #check to see if button 0 is pressed
β if not held[0]: #check to make sure the held variable isn't true
β print("Zoom in or shift z") #print action to serial monitor
β kbd.send(Keycode.SHIFT,Keycode.Z) #send the keyboard command Shift Z to the device
β held[0] = 1 #change the held variable for this button to trueThe next three commands I thought I would add would be to go directly to certain views. I βdecided to use buttons 3, 7, and 11 and include the commands to snap to the front view, top βview, and isometric view. The commands for these three are SHIFT 1 for front view, SHIFT 5 for βTop view, and SHIFT 7 for isometric view. I find myself using these buttons quite often to jump βto these three views so I thought these would be good choices for this device. I also chose to βhave this colored blue, so I created a variable and applied that color to those pixels.β
Example of the snap to front view code:ββ
elif pressed[3]: #check to see if button 3 is pressed
β if not held[3]:#check to make sure the held variable isn't true
β print("Front View or Shift 1") #print action to serial monitor
β kbd.send(Keycode.SHIFT, Keycode.ONE)#send the keyboard command Shift, One to the deviceβ
β held[3] = 1 #change the held variable for this button to trueThe next two actions I decided to add were New Sketch and Extrude. I use these probably the βmost out of all the commands up to this point. For these two, I chose to use the buttons labeled βC and D. As has been a theme with this project and CircuitPython, the code was very easy to βadd to the buttons. I chose to color these two buttons to be Violet. After setting up a variable for βthe color, I then proceeded to code in the keycodes for each, SHIFT S for a new sketch and SHIFT βE for extrude. After saving and updating the code, I went back to OnShape to test. Just like βbefore these were working flawlessly. β
Code for new sketch and new extrude:β
elif pressed[12]: #check to see if button 12 is pressed
β if not held[12]:#check to make sure the held variable isn't true
β print("New Sketch or Shift s") #print action to serial monitor
β kbd.send(Keycode.SHIFT, Keycode.S)#send the keyboard command Shift, S to the device
β held[12] = 1 #change the held variable for this button to true
β β
β elif pressed[13]: #check to see if button 13 is pressed
β if not held[13]:#check to make sure the held variable isn't true
β print("New Extrude or Shift e") #print action to serial monitor
β kbd.send(Keycode.SHIFT, Keycode.E)#send the keyboard command Shift, E to the device
β held[13] = 1 #change the held variable for this button to trueWhile testing out the new sketch command, I thought it would be nice to have the function to βtoggle between a regular line and a construction line in the sketch command. I decided to use βthe button labeled E for this. I set the color to orange and entered the keycode Q into the code. β
Construction/ regular line toggle code:ββ
elif pressed[14]: #check to see if button 14 is pressed
β if not held[14]:#check to make sure the held variable isn't true
β print("Toggle Construction line in Sketch or Q") #print action to serial monitor
β kbd.send(Keycode.Q)#send the keyboard command Q to the device
β held[14] = 1 #change the held variable for this button to trueFor the last button, it took me a while to decide what command to use. After looking through all βof the shortcuts, I decided to add a clear selection button. I added the variable for the color red βand then added the keycode command of SPACEBAR to the code for button F. I then saved the βcode and went back to Onshape for a final test. For the final test, I opened one of my previous βdesigns and started by zooming way in and then way out. Next, I pushed the zoom to fit button βand the object filled the screen. I then pressed the zoom to window button and used my mouse βto zoom in to the top left corner of the object. I then proceeded to rotate the part to the left βand right, followed by up and down. From there, I snapped to the front view, the top view, then βthe isometric view. After changing the views, I pressed the new sketch button and clicked on βone of the faces of the object. I chose the line command and started drawing a line. As I was βdragging the line across the object, I pressed the line type toggle button, and the line changed βover to a construction line. Excellent!! I then pressed the red X to cancel out of the new sketch. βOnce that was canceled, I pressed the new extrude button and selected the face of the object βagain. Again, this worked flawlessly. Last, I selected two faces of the object, and after they were βhighlighted, I pressed the clear selection button.
βAfter finishing this project, I was shocked by how easy it was to program and get up and βrunning. Also, I was somewhat taken aback by how easy it was to make changes to the code and βtest those changes. If you have not tried CircuitPython, I highly recommend you check it out. βThere are tons of resources out there that make using it very easy. β
Going forward, Iβve had the idea to adapt this so that it can also work for Fusion 360. In the little βbit of looking into using this for fusion 360, I did notice some changes need that need to be βmade to the code to get this to work as it does in OnShape. For example, it looks like I will have βto emulate a mouse to be able to make the part rotate. Fusion 360 uses a middle mouse button βto enable rotation. This will require using the Adafruit HID library for the mouse, however, I βthink it should be easy to implement. Another option would be to try out Adafruitβs Macropad, βwhich would enable a lot more commands by setting up a number of different pages of βcommands by using the encoder to select which page and then programming each page for a βdifferent area of the CAD software Iβm using.
βHopefully, you have found this project writeup very useful and it has inspired you to create a βsimilar project of your own. β
I took a short video of the device operating in OnShape.
Here is the full code for this project:β
import time
import board
import busio
import usb_hid
from adafruit_bus_device.i2c_device import I2CDevice
import adafruit_dotstar
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode
from digitalio import DigitalInOut, Direction, Pull
cs = DigitalInOut(board.GP17)β
cs.direction = Direction.OUTPUT
cs.value = 0β
num_pixels = 16β
pixels = adafruit_dotstar.DotStar(board.GP18, board.GP19, num_pixels, brightness=0.1, βauto_write=True)β
i2c = busio.I2C(board.GP5, board.GP4)β
device = I2CDevice(i2c, 0x20)β
kbd = Keyboard(usb_hid.devices)β
layout = KeyboardLayoutUS(kbd)β
def read_button_states(x, y):β
β pressed = [0] * 16β
β with device:β
β device.write(bytes([0x0]))β
β result = bytearray(2)β
β device.readinto(result)β
β b = result[0] | result[1] << 8β
β for i in range(x, y):β
β if not (1 << i) & b:β
β pressed[i] = 1β
β else:β
β pressed[i] = 0β
β return pressed
held = [0] * 16β
β#The below colors are set up so that we don't have to repeat the RGB code multiple timesβ
green = (0,255,0)β
white = (100,100,100)β
red = (255,0,0)β
orange = (255,128,0)β
light_red = (255,25,25)β
violet = (89,0,179)β
blue = (0,0,255)β
pan = 0 # Pan 1 means that the Control and shift key will be on
pixels[5] = orange #turn pixel 5 on prior to starting the sketch
while True:β
β pressed = read_button_states(0, 16)β
β#Color coding the buttons according to thier functionβ
β pixels[0] = white
β pixels[1] = green
β pixels[2] = white
β pixels[3] = blue
β pixels[4] = green
β pixels[6] = green
β pixels[7] = blue
β pixels[8] = white
β pixels[9] = green
β pixels[10] = white
β pixels[11] = blue
β pixels[12] = violet
β pixels[13] = violet
β pixels[14] = orange
β pixels[15] = red
β β
β if pressed[0]: #check to see if button 0 is pressed
β if not held[0]: #check to make sure the held variable isn't true
β print("Zoom in or shift z") #print action to serial monitor
β kbd.send(Keycode.SHIFT,Keycode.Z) #send the keyboard command Shift Z to the device
β held[0] = 1 #change the held variable for this button to true
β β
β β
β elif pressed[1]: #check to see if button 1 is pressed
β# if not held[1]:#check to make sure the held variable isn't trueβ
β if pan != 1:β
β print("Up Arrow") #print action to serial monitor
β kbd.send(Keycode.UP_ARROW)#send the keyboard command Up arrow to the device
β time.sleep(0.1)β
β# held[1] = 1β
β β
β else:β
β print("Up Arrow with Control and Shift") #print action to serial monitor
β kbd.send(Keycode.CONTROL, Keycode.SHIFT, Keycode.UP_ARROW)#send the keyboard βcommand Shift, Up arrow to the device
β# time.sleep(0.1)β
β# held[1] = 1β
β β
β elif pressed[2]: #check to see if button 2 is pressed
β if not held[2]: #check to make sure the held variable isn't true
β print("Zoom in or z") #print action to serial monitor
β kbd.send(Keycode.Z) #send the keyboard command Z to the device
β held[2] = 1 #change the held variable for this button to true
β β
β β
β elif pressed[3]: #check to see if button 3 is pressed
β if not held[3]:#check to make sure the held variable isn't true
β print("Front View or Shift 1") #print action to serial monitor
β kbd.send(Keycode.SHIFT, Keycode.ONE)#send the keyboard command Shift, One to the device
β held[3] = 1 #change the held variable for this button to true
β β
β elif pressed[4]: #check to see if button 4 is pressed
β β
β# if not held[4]: #check to make sure the held variable isn't true β
β if pan != 1:β
β print("Left Arrow") #print action to serial monitor
β kbd.send(Keycode.LEFT_ARROW)#send the keyboard command Left Arrrow to the device
β time.sleep(0.1)β
β# held[4] = 1β
β else:β
β print("Left Arrow with Control and Shift") #print action to serial monitor
β kbd.send(Keycode.CONTROL, Keycode.SHIFT, Keycode.LEFT_ARROW)#send the keyboard βcommand Shift, Left Arrrow to the device
β time.sleep(0.1)β
β# held[4] = 1β
β β
β elif pressed[5]: #check to see if button 5 is pressed
β β
β if not held[5]:#check to make sure the held variable isn't true β
β if pan != 1: # check to see if the pan variable is not equal to 1β
β pixels[5] = light_red #set the pixel to light red
β pan = 1 #set the pan variable to 1β
β print("Control Shift ON") #print action to serial monitor
β held[5] = 1 #change the held variable for this button to true
β β
β elif pan == 1: # if the pan variable is equal to 1β
β pixels[5] = orange #set the pixel to orange
β pan = 0 #set the pan variable to 0β
β print("Control Shift OFF") #print action to serial monitor
β held[5] = 1 #change the held variable for this button to true
β β
β β
β β
β elif pressed[6]: #check to see if button 6 is pressed
β β
β# if not held[6]: #check to make sure the held variable isn't trueβ
β if pan != 1:β
β print("Right Arrow") #print action to serial monitor
β kbd.send(Keycode.RIGHT_ARROW)#send the keyboard command Right Arrrow to the device
β time.sleep(0.1)β
β# held[6] = 1β
β else:β
β print("Right Arrow with Control and Shift") #print action to serial monitor
β kbd.send(Keycode.CONTROL, Keycode.SHIFT, Keycode.RIGHT_ARROW)#send the keyboard βcommand Shift, Right Arrrow to the device
β time.sleep(0.1)β
β# held[1] = 1β
β β
β elif pressed[7]: #check to see if button 7 is pressed
β if not held[7]:#check to make sure the held variable isn't true
β print("Top View or Shift 5") #print action to serial monitor
β kbd.send(Keycode.SHIFT, Keycode.FIVE)#send the keyboard command Shift, Five to the device
β held[7] = 1 #change the held variable for this button to true
β β
β elif pressed[8]: #check to see if button 8 is pressed
β if not held[8]:#check to make sure the held variable isn't true
β print("Zoom to fit or f") #print action to serial monitor
β kbd.send(Keycode.F)#send the keyboard command F to the device
β held[8] = 1 #change the held variable for this button to true
β elif pressed[9]: #check to see if button 9 is pressedβ
β β
β# if not held[9]:#check to make sure the held variable isn't trueβ
β if pan != 1:β
β print("Down Arrow") #print action to serial monitor
β kbd.send(Keycode.DOWN_ARROW)#send the keyboard command Down Arrow to the device
β time.sleep(0.1)β
β# held[9] = 1β
β else:β
β print("Down Arrow with Control and Shift") #print action to serial monitor
β kbd.send(Keycode.CONTROL, Keycode.SHIFT, Keycode.DOWN_ARROW)#send the keyboard βcommand Shift, Down Arrow to the device
β time.sleep(0.1)β
β# held[1] = 1β
β β
β β
β elif pressed[10]: #check to see if button 10 is pressed
β if not held[10]:#check to make sure the held variable isn't true
β print("Zoom to window or w") #print action to serial monitor
β kbd.send(Keycode.W)#send the keyboard command W to the device
β held[10] = 1 #change the held variable for this button to true
β β
β elif pressed[11]: #check to see if button 11 is pressed
β if not held[11]:#check to make sure the held variable isn't true
β print("Isometric View or Shift 7") #print action to serial monitor
β kbd.send(Keycode.SHIFT, Keycode.SEVEN)#send the keyboard command Shift, Seven to the βdevice
β held[11] = 1 #change the held variable for this button to true
β β
β elif pressed[12]: #check to see if button 12 is pressed
β if not held[12]:#check to make sure the held variable isn't true
β print("New Sketch or Shift s") #print action to serial monitor
β kbd.send(Keycode.SHIFT, Keycode.S)#send the keyboard command Shift, S to the device
β held[12] = 1 #change the held variable for this button to true
β β
β elif pressed[13]: #check to see if button 13 is pressed
β if not held[13]:#check to make sure the held variable isn't true
β print("New Extrude or Shift e") #print action to serial monitor
β kbd.send(Keycode.SHIFT, Keycode.E)#send the keyboard command Shift, E to the device
β held[13] = 1 #change the held variable for this button to true
β β
β elif pressed[14]: #check to see if button 14 is pressed
β if not held[14]:#check to make sure the held variable isn't true
β print("Toggle Construction line in Sketch or Q") #print action to serial monitor
β kbd.send(Keycode.Q)#send the keyboard command Q to the device
β held[14] = 1 #change the held variable for this button to trueβ
β β
β elif pressed[15]: #check to see if button 15 is pressed
β if not held[15]:#check to make sure the held variable isn't true
β print("Clear Selection or SPACEBAR") #print action to serial monitor
β kbd.send(Keycode.SPACEBAR)#send the keyboard command Spacebar to the device
β held[15] = 1 #change the held variable for this button to true
β else: # Released state
β for i in range(16):β
β held[i] = 0 # Set held states to off
β time.sleep(0.1) # Debounce

