-
Notifications
You must be signed in to change notification settings - Fork 0
Home
For now, I will explain what I have done and what I plan on doing on this project.
The 'BBK3' is a small cube-like keyboard. it is small enough to be held in one hand and it can act like a controller to use in games. It is composed of a Seeed XIAO nrf52840 sense and 5 switches, RGB lights and custom made key caps.
At the beginning of the project, the cube was using python with CircuitPython to use different components of the board. I spent the first weeks trying to learn CircuitPython and coding on SoCs because it was a first for me.
Archive of the latest code in python :
"""
import time
import board
from digitalio import DigitalInOut, Pull
from adafruit_debouncer import Debouncer
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
import neopixel
print("- Deco Keypad -")
time.sleep(1) # Sleep for a bit to avoid a race condition on some systems
# ----- Keymap ----- #
# change as needed, e.g. capital A (Keycode.SHIFT, Keycode.A)
switch_a_output = Keycode.A
switch_b_output = Keycode.W
switch_c_output = Keycode.D
switch_d_output = Keycode.S
switch_e_output = Keycode.SPACE
# ----- Keyboard setup ----- #
keyboard = Keyboard(usb_hid.devices)
keyboard_layout = KeyboardLayoutUS(keyboard) # We're in the US :)
# ----- Key setup ----- #
switch_a_in = DigitalInOut(board.D1)
switch_b_in = DigitalInOut(board.D2)
switch_c_in = DigitalInOut(board.D3)
switch_d_in = DigitalInOut(board.D4)
switch_e_in = DigitalInOut(board.D5)
switch_a_in.pull = Pull.UP
switch_b_in.pull = Pull.UP
switch_c_in.pull = Pull.UP
switch_d_in.pull = Pull.UP
switch_e_in.pull = Pull.UP
switch_a = Debouncer(switch_a_in)
switch_b = Debouncer(switch_b_in)
switch_c = Debouncer(switch_c_in)
switch_d = Debouncer(switch_d_in)
switch_e = Debouncer(switch_e_in)
# ----- NeoPixel setup ----- #
MAGENTA = 0xFF00FF
CYAN = 0x0088DD
WHITE = 0xCCCCCC
BLACK = 0x000000
pixel_pin = board.D0
pixels = neopixel.NeoPixel(pixel_pin, 5, brightness=0.25)
pixels.fill(BLACK)
time.sleep(0.3)
pixels.fill(WHITE)
time.sleep(0.3)
pixels.fill(BLACK)
time.sleep(0.3)
pixels[0] = MAGENTA
pixels[1] = CYAN
pixels[2] = MAGENTA
pixels[3] = CYAN
pixels[4] = MAGENTA
while True:
switch_a.update() # Debouncer checks for changes in switch state
switch_b.update()
switch_c.update()
switch_d.update()
switch_e.update()
if switch_a.fell:
keyboard.press(switch_a_output)
pixels[0] = WHITE
if switch_a.rose:
keyboard.release(switch_a_output)
pixels[0] = MAGENTA
if switch_b.fell:
keyboard.press(switch_b_output)
pixels[1] = WHITE
if switch_b.rose:
keyboard.release(switch_b_output)
pixels[1] = CYAN
if switch_c.fell:
keyboard.press(switch_c_output)
pixels[2] = WHITE
if switch_c.rose:
keyboard.release(switch_c_output)
pixels[2] = MAGENTA
if switch_d.fell:
keyboard.press(switch_d_output)
pixels[3] = WHITE
if switch_d.rose:
keyboard.release(switch_d_output)
pixels[3] = CYAN
if switch_e.fell:
keyboard.press(switch_e_output)
pixels[4] = WHITE
if switch_e.rose:
keyboard.release(switch_e_output)
pixels[4] = MAGENTA
"""
from _bleio import adapter
from board import IMU_PWR, IMU_SCL, IMU_SDA
from busio import I2C
from digitalio import DigitalInOut, Direction
from time import sleep
from adafruit_lsm6ds.lsm6ds3 import LSM6DS3
DEVICE_NAME = "XIAO nRF52840 Sense"
INTERVAL = 0.1
SENSITIVITY = 0.01
# Turn on IMU and wait 50 ms
imu_pwr = DigitalInOut(IMU_PWR)
imu_pwr.direction = Direction.OUTPUT
imu_pwr.value = True
sleep(0.05)
# Set up I2C bus and initialize IMU
i2c_bus = I2C(IMU_SCL, IMU_SDA)
sensor = LSM6DS3(i2c_bus)
class BTHomeAdvertisement:
_ADV_FLAGS = [0x02, 0x01, 0x06]
_ADV_SVC_DATA = [0x06, 0x16, 0xD2, 0xFC, 0x40, 0x22, 0x00]
def _name2adv(self, local_name):
adv_element = bytearray([len(local_name) + 1, 0x09])
adv_element.extend(bytes(local_name, "utf-8"))
return adv_element
def __init__(self, local_name=None):
if local_name:
self.adv_local_name = self._name2adv(local_name)
else:
self.adv_local_name = self._name2adv(adapter.name)
def adv_data(self, movement):
adv_data = bytearray(self._ADV_FLAGS)
adv_svc_data = bytearray(self._ADV_SVC_DATA)
adv_svc_data[-1] = movement
adv_data.extend(adv_svc_data)
adv_data.extend(self.adv_local_name)
return adv_data
bthome = BTHomeAdvertisement(DEVICE_NAME)
while True:
gyro_x, gyro_y, gyro_z = sensor.gyro
moving = gyro_x**2 + gyro_y**2 + gyro_z**2
if moving > SENSITIVITY:
print("Moving")
print((gyro_x, gyro_y, gyro_z))
adv_data = bthome.adv_data(1)
else:
adv_data = bthome.adv_data(0)
adapter.start_advertising(
adv_data, scan_response=None, connectable=False, interval=INTERVAL * 2
)
sleep(INTERVAL)
adapter.stop_advertising()
I then switched to arduino because it's in C++, a language I am a bit more familiar with (even though Python is easy to use). I mainly did the switch because i saw that there was a lot of documentation, examples and even forum posts about arduino, plus a lot of what i see online, even though it's not entirely made for my board, provide a great starting point for a direction to follow.
The code is not finished yet so I will update this page later.
WIP
https://wiki.seeedstudio.com/XIAO_BLE/
https://learn.adafruit.com/circuitpython-essentials/circuitpython-essentials
https://learn.adafruit.com/welcome-to-circuitpython/overview
https://docs.circuitpython.org/projects/lsm6dsox/en/latest/
https://github.com/koenvervloesem/BTHome-Inertial-Sensor-in-CircuitPython
https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html
https://learn.adafruit.com/custom-hid-devices-in-circuitpython?view=all
https://circuitpython-joystickxl.readthedocs.io/en/stable/intro.html
A lot of the current code is from built from examples provided by the libraries downloaded or already on the board
https://github.com/adafruit/Adafruit_NeoPixel
https://github.com/adafruit/Adafruit_TinyUSB_Arduino
https://github.com/Seeed-Studio/Seeed_Arduino_LSM6DS3
https://hardwaretester.com/gamepad
https://docs.unity3d.com/Packages/[email protected]/manual/Layouts.html
https://docs.unity3d.com/Packages/[email protected]/manual/HID.html
https://forum.unity.com/threads/new-input-system-custom-input-device-analog-reading-as-0-1-0-1-for-1-1.1116076/