chebe: (Default)
chebe ([personal profile] chebe) wrote2021-04-01 07:07 pm

PicoPlanet Video Call Controller

A while back I picked up a very cute circuit python board with procedurally generated graphics called the PicoPlanet. (I got design number 12.) A few months into the Pandemic, a bunch of projects around making video calls easier to use appeared. Adafruit even has one for circuit python; a video call panic button, for PyRuler. I found their setup, which mutes audio and turns off video at the same time, didn't work for me. Mostly because the controls in these apps are mostly toggles. So if I had my video on, but microphone off, and I hit that button, I'd be turning off my camera but turning on my microphone. Instead I broke the controls down to;
  • button one un/mutes my microphone, in all my most common applications,

  • button two turns on/off my camera, in all my most common applications,

  • button three un/mutes the speakers on my computer.

code.py;

# install adafruit HID library to use keyboard functionality
# see https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases

# https://learn.adafruit.com/PyRulerVideoPanic/code

# https://circuitpython.readthedocs.io/projects/hid/en/latest/api.html#adafruit-hid-keycode-keycode

import time
import board
import touchio
import pulseio
from digitalio import DigitalInOut, Direction, Pull
import usb_hid
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode

from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS


#init touch buttons
touch1 = touchio.TouchIn(board.A0)
touch2 = touchio.TouchIn(board.A1)
touch3 = touchio.TouchIn(board.A2)

#init led lines
ledG = DigitalInOut(board.D5)
ledG.direction = Direction.OUTPUT
ledR = DigitalInOut(board.D6)
ledR.direction = Direction.OUTPUT
ledB = DigitalInOut(board.D7)
ledB.direction = Direction.OUTPUT

time.sleep(1)  # Sleep for a bit to avoid a race condition on some systems
cc = ConsumerControl(usb_hid.devices)

kbd = Keyboard(usb_hid.devices)
layout = KeyboardLayoutUS(kbd)


while True:
    if touch1.raw_value > 2500:
        ledR.value = False

        # Zoom; un/mutes microphone
        kbd.press(Keycode.LEFT_ALT, Keycode.A)
        time.sleep(0.25)
        kbd.release_all()

        # Skype, or Ctrl-M, Shift-K ?
        kbd.press(Keycode.APPLICATION, Keycode.F4)
        time.sleep(0.25)
        kbd.release_all()

        # Discord; un/mute microphone
        kbd.press(Keycode.LEFT_CONTROL, Keycode.SHIFT, Keycode.M)
        kbd.release_all()
        time.sleep(0.25)

        time.sleep(0.2)
    else:
        ledR.value = True


    if touch2.raw_value > 2500:
        ledG.value = False

        # Zoom; un/mutes video
        kbd.press(Keycode.LEFT_ALT, Keycode.V)
        time.sleep(0.25)
        kbd.release_all()

        # Skype, or Ctrl-M, Shift-K ?
        kbd.press(Keycode.APPLICATION, Keycode.F5)
        time.sleep(0.25)
        kbd.release_all()

        time.sleep(0.2)
    else:
        ledG.value = True


    if touch3.raw_value > 2500:
        cc.send(ConsumerControlCode.MUTE)
        ledB.value = False
		
        time.sleep(0.2)
    else:
        ledB.value = True


Which works great (for Zoom and Discord, Skype is experimental), but the board dangling at the end of a USB cable isn't the easiest to grab. So when I got a 3D printer the first thing I printed was a case.

The PicoPlanet github contains a two-piece frame case, and a link to a bumper case. I went with the bumper case because I didn't want to obscure the design. I printed the closed back version, and it was a snug fit, with some gentle hammering to get it in flat. But it definitely makes it easier to grab.



Closed bumper case for PicoPlanet on 3D printer bed
Photo by [personal profile] chebe





Closed bumper case on PicoPlanet (design #12)
Photo by [personal profile] chebe