This is an old revision of the document!
Un Macropad programabil cu scopul de a eficientiza lucrul pe calculator. Am plecat de la dorinta de a controla mai eficient functionalitati ale laptopului meu in timp ce lucrez precum:
Acest proiect este util pentru minimizarea timpului mort
Lista componente:
Codul a fost dezvoltat folosind limbajul CircuitPython in Thonny. Biblioteci externe:
Codul citeste semnale de la cele 10 butoane si de la codorul rotativ, inclusiv butonul acestuia
Pentru a programa functionalitatea celor 10 butoane, trebuie definita o matrice de 5×2 cu functionalitatea pentru foecare butoane. Functionalitatea butoanelor este preluata din biblioteca Adafruit HID.
Pentru controlul OLED-ului se foloseste biblioteca Adafruit SSD1306 si Adafruit ImageLoader. Se pot scrie mesaje caracter cu caracter, se pot incarca imagini sau se pot seta pixeli arbitrar pe o matrice de 128×64 pixeli.
import rotaryio import board import digitalio import displayio import adafruit_imageload import usb_hid from adafruit_hid.consumer_control import ConsumerControl from adafruit_hid.consumer_control_code import ConsumerControlCode import time from digitalio import DigitalInOut, Direction, Pull from adafruit_hid.keyboard import Keyboard from adafruit_hid.keycode import Keycode import busio import adafruit_ssd1306 #display i2c = busio.I2C(board.GP27, board.GP26) display = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c) # left encoder buttonL = digitalio.DigitalInOut(board.GP6) buttonL.direction = digitalio.Direction.INPUT buttonL.pull = digitalio.Pull.UP encoderL = rotaryio.IncrementalEncoder(board.GP7, board.GP8) cc = ConsumerControl(usb_hid.devices) button_stateL = None last_positionL = encoderL.position # keyboard led = DigitalInOut(board.LED) led.direction = Direction.OUTPUT led.value = True kbd = Keyboard(usb_hid.devices) cck = ConsumerControl(usb_hid.devices) pins = [ board.GP13, board.GP12, board.GP11, board.GP10, board.GP16, board.GP17, board.GP18, board.GP19, board.GP20, board.GP21, ] MEDIA = 1 KEY = 2 META = 3 # functionality of each layer keymap_layers = [{ (0): (KEY, [Keycode.ONE]), (1): (KEY, [Keycode.TWO]), (2): (KEY, [Keycode.THREE]), (3): (KEY, [Keycode.FOUR]), (4): (META, [Keycode.CAPS_LOCK]), (5): (KEY, (Keycode.SHIFT, Keycode.GUI, Keycode.M)), (6): (KEY, [Keycode.FIVE]), (7): (KEY, [Keycode.SIX]), (8): (KEY, [Keycode.SEVEN]), (9): (KEY, [Keycode.EIGHT]), }, { (0): (KEY, [Keycode.NINE]), (1): (KEY, [Keycode.ZERO]), (2): (KEY, (Keycode.SHIFT, Keycode.NINE)), (3): (KEY, (Keycode.SHIFT, Keycode.ZERO)), (4): (META, [Keycode.CAPS_LOCK]), (5): (KEY, (Keycode.SHIFT, Keycode.GUI, Keycode.M)), (6): (KEY, (Keycode.SHIFT, Keycode.THREE)), (7): (KEY, (Keycode.SHIFT, Keycode.FOUR)), (8): (KEY, (Keycode.SHIFT, Keycode.SEVEN)), (9): (KEY, (Keycode.SHIFT, Keycode.EIGHT)), }] keymap = keymap_layers[0] layer = True mute = False # display layers based on keyboard layer def change_layer(mute): global keymap if layer: display.fill(0) keymap = keymap_layers[not layer] display.text("layer 1 2 3 4", 0, 0, 1) if mute == True: display.text("unmute 5 6 7 8", 0, 32, 1) else: display.text("mute 5 6 7 8", 0, 32, 1) display.show() else: display.fill(0) keymap = keymap_layers[not layer] display.text("layer 9 0 ( )", 0, 0, 1) if mute == True: display.text("unmute # $ & *", 0, 32, 1) else: display.text("mute # $ & *", 0, 32, 1) display.show() switches = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] for i in range(10): switches[i] = DigitalInOut(pins[i]) switches[i].direction = Direction.INPUT switches[i].pull = Pull.UP switch_state = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # init change_layer(mute) while True: # left encoder current_positionL = encoderL.position position_changeL = current_positionL - last_positionL if position_changeL > 0: for _ in range(position_changeL): cc.send(ConsumerControlCode.VOLUME_DECREMENT) #print(current_positionL) elif position_changeL < 0: for _ in range(-position_changeL): cc.send(ConsumerControlCode.VOLUME_INCREMENT) #print(current_positionL) last_positionL = current_positionL if not buttonL.value and button_stateL is None: button_stateL = "pressed" if buttonL.value and button_stateL == "pressed": cc.send(ConsumerControlCode.MUTE) button_stateL = None # keyboard for button in range(10): if switch_state[button] == 0: if not switches[button].value: try: if keymap[button][0] == KEY: if button == 5: mute = not mute change_layer(mute) kbd.press(*keymap[button][1]) else: if button == 4: layer = not layer change_layer(mute) else: cck.send(keymap[button][1]) except ValueError: # deals w six key limit pass switch_state[button] = 1 if switch_state[button] == 1: if switches[button].value: try: if keymap[button][0] == KEY: kbd.release(*keymap[button][1]) except ValueError: pass switch_state[button] = 0 time.sleep(0.01) # debounce
Fişierele se încarcă pe wiki folosind facilitatea Add Images or other files. Namespace-ul în care se încarcă fişierele este de tipul :pm:prj20??:c? sau :pm:prj20??:c?:nume_student (dacă este cazul). Exemplu: Dumitru Alin, 331CC → :pm:prj2009:cc:dumitru_alin.