The Raspberry Pi 500+ keyboard has individually controllable RGB lights. Besides decorative effects, the LEDs can communicate useful information: a key could change colour when a build finishes, a message arrives, a monitored value crosses a threshold, or another event that needs attention.
The rpi-keyboard-config package provides both a command-line tool and a Python interface for controlling the keyboard. It can be installed with:
sudo apt install rpi-keyboard-config
The keyboard firmware must also support RGB control.
Setting One Key to an RGB Colour
The library stores LED colours as HSV values in the range 0–255. This minimal example accepts a familiar RGB value, converts it to the required representation, and sets one key by LED index:
from colorsys import rgb_to_hsv
from RPiKeyboardConfig import RPiKeyboardConfig
key_index = 0
rgb = (255, 0, 0) # Red
hsv = tuple(round(value * 255) for value in rgb_to_hsv(*(value / 255 for value in rgb)))
keyboard = RPiKeyboardConfig()
keyboard.set_led_direct_effect()
keyboard.set_led_by_idx(idx=key_index, colour=hsv)
keyboard.send_leds()
Changing key_index selects another key, while rgb accepts red, green, and blue values from 0 to 255. Calling send_leds() applies the pending change to the keyboard.
While experimenting with direct LED control, I created nine lighting modes. Three of them are shown below.
Mode 2: Row Sweep
Mode 2 illuminates the keyboard one row at a time. Alternate rows run in opposite directions, producing a sweep across the physical key layout.
Mode 7: Pulsing Keyboard
Mode 7 applies one hue to every key and repeatedly varies the brightness, creating a full-keyboard pulse. The same approach could be used as a persistent status indicator.
Mode 9: Pointer Position
Mode 9 maps the mouse-pointer position on the display to the keyboard matrix and illuminates the corresponding key. A left click increases its brightness, while a middle click selects a random colour.
The following standalone example implements the complete pointer-to-key effect:
import random
import time
import mouse
import pyautogui
from RPiKeyboardConfig import RPiKeyboardConfig
ROW_STARTS = (0, 16, 31, 46, 60)
def map_range(value, in_min, in_max, out_min, out_max):
return (value - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
def set_led_pixel(keyboard, row, column, hue, saturation, brightness):
row = max(0, min(4, row))
column = max(0, min(14, column))
# The Enter key occupies the final position on row 3.
if row == 3:
column = min(column, 13)
selected_led = ROW_STARTS[row] + column
for led_index in range(85):
colour = (hue, saturation, brightness) if led_index == selected_led else (0, 0, 0)
keyboard.set_led_by_idx(idx=led_index, colour=colour)
keyboard.send_leds()
keyboard = RPiKeyboardConfig()
keyboard.set_led_direct_effect()
keyboard.rgb_clear()
screen_width, screen_height = pyautogui.size()
while True:
pointer_x, pointer_y = pyautogui.position()
key_row = int(map_range(pointer_y, 0, screen_height - 1, 0, 4))
key_column = int(map_range(pointer_x, 0, screen_width - 1, 0, 14))
if mouse.is_pressed(button="left"):
hue, brightness = 128, 255
elif mouse.is_pressed(button="middle"):
hue, brightness = random.randint(0, 255), 255
else:
hue, brightness = 128, 160
set_led_pixel(keyboard, key_row, key_column, hue, 255, brightness)
time.sleep(0.01)
pyautogui is needed to read the desktop dimensions and current pointer coordinates. The mouse package independently reports whether the left or middle mouse button is pressed, allowing button state to modify the key colour.
The horizontal pointer coordinate is scaled from the screen width to keyboard columns 0–14. The vertical coordinate is scaled from the screen height to rows 0–4. The pointer is mapped across the upper five keyboard rows; the bottom row, which contains the large spacebar, is excluded because it does not fit the regular grid used for pointer tracking. set_led_pixel() converts that row and column into the linear LED index used by the keyboard library, switches off every other LED, assigns the selected HSV colour, and sends the completed update to the keyboard. As the pointer moves, the calculated row and column change, so the illuminated key follows it.