├── Teams Buttons Instructions.pdf ├── LICENSE ├── README.md └── code.py /Teams Buttons Instructions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TellinStories/Teams-Shortcut-Buttons/HEAD/Teams Buttons Instructions.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 BrainJar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | I spend a lot of my work day in Teams meetings and frequently need to mute / unmute my microphone, turn my camera on and off, or raise or lower my hand. 2 | If using my mouse I invariably can’t find the right icon to click fast enough and I never remember the right keyboard shortcuts. 3 | So I built a simple device so that I can press one big fat arcade button for each of those actions. 4 | ![IMG_7282](https://github.com/user-attachments/assets/e70f9911-f114-4600-92f9-e8fb5044c0d4) 5 | 6 | 7 | The device is simple – three arcade buttons which are connected to an RP2040 Zero microcontroller. 8 | I chose the RP2040 because it is cheap, very small and I am already used to using Raspberry Pi Picos (which would also work well); other microcontrollers may also be suitable but I am not experienced in using them. 9 | The microcontroller runs a simple program that sends the keyboard shortcuts to your computer when a button is pressed, as if it were a keyboard. 10 | For example, if you press the microphone mute / unmute button then “CTRL+SHIFT+M” is sent to your computer which is the mute / unmute shortcut. 11 | Each button press toggles the LED built into the arcade button between on and off. 12 | 13 | The program is written in Circuit Python and requires the Adafruit HID Library https://docs.circuitpython.org/projects/hid/en/latest/index.html and https://github.com/adafruit/Adafruit_CircuitPython_Bundle 14 | You need to copy the library files from the the Adafruit HID Library to your RP2040 / Raspberry Pi Pico library folder and then copy the code.py file from this GitHub. 15 | 16 | Full instructions are in the Teams Buttons Instructions PDF file. 17 | The 3D printing files can be found here: https://makerworld.com/en/models/1436571-teams-shortcut-buttons#profileId-1494585 18 | 19 | I took inspiration from this project: https://github.com/ttan/Mute-o-Matic-V2 - thank you to the author. 20 | -------------------------------------------------------------------------------- /code.py: -------------------------------------------------------------------------------- 1 | # Imports 2 | import board 3 | import digitalio 4 | import usb_hid 5 | from adafruit_hid.keyboard import Keyboard 6 | from adafruit_hid.keycode import Keycode 7 | import time 8 | 9 | # Constants 10 | DEBOUNCE_TIME = 0.1 # Debounce time set at this number of seconds 11 | STARTUP_BLINK_TIME = 0.2 # The LEDs blink at start up for this number of seconds 12 | 13 | # Setting up the buttons 14 | # Button 1 (Hand) on GPIO14 15 | button1 = digitalio.DigitalInOut(board.GP14) 16 | button1.direction = digitalio.Direction.INPUT 17 | button1.pull = digitalio.Pull.UP # Pull Ups as button connects to GND when pressed 18 | 19 | # Button 2 (Camera) on GPIO26 20 | button2 = digitalio.DigitalInOut(board.GP26) 21 | button2.direction = digitalio.Direction.INPUT 22 | button2.pull = digitalio.Pull.UP 23 | 24 | # Button 3 (Microphone) on GPIO28 25 | button3 = digitalio.DigitalInOut(board.GP28) 26 | button3.direction = digitalio.Direction.INPUT 27 | button3.pull = digitalio.Pull.UP 28 | 29 | # Setting up the LEDs 30 | # Button 1 (Hand) LED - LED1 on GPIO15 31 | led1 = digitalio.DigitalInOut(board.GP15) 32 | led1.direction = digitalio.Direction.OUTPUT 33 | led1.value = False # Sets the LED to off 34 | 35 | # Button 2 (Camera) LED - LED2 on GPIO27 36 | led2 = digitalio.DigitalInOut(board.GP27) 37 | led2.direction = digitalio.Direction.OUTPUT 38 | led2.value = False # Sets the LED to off 39 | 40 | # Button 3's LED - LED2 on GPIO29 41 | led3 = digitalio.DigitalInOut(board.GP29) 42 | led3.direction = digitalio.Direction.OUTPUT 43 | led3.value = False # Sets the LED to off 44 | 45 | # Set up the keyboard 46 | keyboard = Keyboard(usb_hid.devices) 47 | 48 | # This makes the LEDs blink at start up 49 | for _ in range(3): 50 | led1.value = True 51 | led2.value = True 52 | led3.value = True 53 | time.sleep(STARTUP_BLINK_TIME) 54 | led1.value = False 55 | led2.value = False 56 | led3.value = False 57 | time.sleep(STARTUP_BLINK_TIME) 58 | 59 | while True: 60 | if button1.value is False: # Button pressed (active low) 61 | led1.value = not led1.value # This toggles the LED on / off 62 | keyboard.press(Keycode.CONTROL, Keycode.SHIFT, Keycode.K) # Mimics pressing CTRL+SHIFT+K 63 | print("Raise / Lower Hand button pressed") 64 | time.sleep(DEBOUNCE_TIME) # Debounce 65 | keyboard.release_all() # Release all keys 66 | while button1.value is False: 67 | time.sleep(0.01) 68 | 69 | if button2.value is False: # Button pressed (active low) 70 | led2.value = not led2.value # This toggles the LED on / off 71 | keyboard.press(Keycode.CONTROL, Keycode.SHIFT, Keycode.O) # Mimics pressing CTRL+SHIFT+O 72 | print("Camera on/off button pressed") 73 | time.sleep(DEBOUNCE_TIME) # Debounce 74 | keyboard.release_all() # Release all keys 75 | while button2.value is False: 76 | time.sleep(0.01) 77 | 78 | if button3.value is False: # Button pressed (active low) 79 | led3.value = not led3.value # This toggles the LED on / off 80 | keyboard.press(Keycode.CONTROL, Keycode.SHIFT, Keycode.M) # Mimics pressing CTRL+SHIFT+M 81 | print("Mute / Unmute button pressed") 82 | time.sleep(DEBOUNCE_TIME) # Debounce 83 | keyboard.release_all() # Release all keys 84 | while button3.value is False: 85 | time.sleep(0.01) 86 | 87 | time.sleep(0.01) # Delay 88 | --------------------------------------------------------------------------------