Translated from: http://www.suppertime.co.uk/blogmywiki/2020/08/ps2-keyboard-microbit/
For many years, I have wanted to connect a regular computer keyboard to the BBC micro:bit to make radio messaging and encryption easier to use. I had seen and used something similar on Arduino, which used a complex C++ library to read data from a PS/2 keyboard, parsing each data bit. But that was not the way I preferred.
Previously, I had connected a thermal printer directly to the micro:bit and sent it some serial data, and it printed the message immediately. I never thought a homemade matrix keyboard would work on the first try, but it did.
Sometimes, it helps to be free from knowledge and tradition, although I must quickly add, except when flying a plane or performing surgery.
Therefore, I decided to take this approach to solve the micro:bit PS/2 keyboard issue.
What is a PS/2 keyboard? A PS/2 keyboard is an old-style keyboard before USB – they have round plugs, usually wrapped in purple plastic, while PS/2 mice often have green plugs. They are not particularly easy to buy, at least not new, but people often throw them away, as we will see…
They are just a matrix of buttons connected to a small microcontroller (which operates at 5 volts, while the micro:bit is 3 volts) that converts key presses into serial data. The protocol is quite daunting… sending an 11-bit data at a frequency between 10 to 16.7 kHz, including:
So I decided to ignore all of this.
One day, while walking my dog, I found a PS/2 keyboard thrown on the roadside, with the plug cut off. I took it home and disassembled it, hoping to understand the function of each colored cable through the PCB. (There is no standard for PS/2 cable colors)
Searching the internet yielded no results. Fortunately, by examining the cut plug, I was able to figure out the functions of this particular Dell keyboard:
Pink = 5v
Black = GND
White = data
Brown = clock
import micropython # to enable disabling of accidental keyboard interrupt
from microbit import *
uart.init(baudrate=10000, bits=8, parity=None, stop=1, tx=None, rx=pin1)
micropython.kbd_intr(-1) # disable accidental keyboard interrupt, no idea if this works or is needed
while True: if uart.any(): data = bytearray(1) uart.readinto(data, 1) display.scroll(data[0])
For example, pressing the letter Q always produces 139, 248, 139, while pressing A produces 142, 248, 142.
From my readings, I learned (it does require a bit of knowledge) that a PS/2 keyboard sends a code when you press a key, and then sends a release code when you let go. So 139, 248, 139 indeed means “press Q”, “release Q”.
So all I had to do was sniff the codes for each key I was interested in and create a dictionary to look them up and convert them to letters. So far, I only care about letters, numbers, and some very basic punctuation, but I have implemented my own caps lock and backspace. (The caps lock light does not light up, but one day…)
The key codes for other keyboards may differ, so if needed, use the sniffer program to create your own list. You may also need to use a different baud rate, but this Dell works at 10,000.
Encrypted Radio Communication Project
Let’s use this newfound knowledge to build a super spy communicator! No one will see you hiding in the bushes with a micro:bit and a Dell PS/2 keyboard pulled from the trash!
Put the program below into the receiving micro:bit:
from microbit import *
import radio
radio.config(group=23)
radio.on()
storedMessage = ''
while True: message = radio.receive() if message: display.scroll(message) storedMessage = message if button_a.was_pressed(): display.scroll(storedMessage)
For the transmitter, use the following program. Remember, you need to connect pin 1 of the micro:bit to the data line of the keyboard – mine is white, but other keyboards may not be. Also, connect the micro:bit 3v pin to the power line of the keyboard (mine is pink) and the micro:bit GND pin to the ground line of the keyboard (on this Dell, it’s black).
import micropython # to enable disabling of accidental keyboard interrupt
from microbit import *
import radio
radio.config(group=23)
uart.init(baudrate=10000, bits=8, parity=None, stop=1, tx=None, rx=pin1)
micropython.kbd_intr(-1) # disable accidental keyboard interrupt if ctrl-C character received on serial input
dataList = []
delay = 250
capsLock = True
message = ''
keyCodes = { 139: 'Q', 207: 'W', 210: 'E', 215: 'R', 150: 'T', 219: 'Y', 222: 'U', 161: 'I', 226: 'O', 231: 'P', 142: 'A', 205: 'S', 145: 'D', 213: 'F', 154: 'G', 217: 'H', 157: 'J', 224: 'K', 224: 'K', 229: 'L', 140: 'Z', 208: 'X', 209: 'C', 148: 'V', 152: 'B', 153: 'N', 220: 'M', 225: ',', 165: '.', 149: '_', 164: '?', 138: '1', 206: '2', 146: '3', 147: '4', 214: '5', 218: '6', 159: '7', 158: '8', 162: '9', 163: '0'}
while True: if uart.any(): data = bytearray(1) uart.readinto(data, 1) dataList.append(data[0]) if len(dataList) == 3: if dataList[0] in keyCodes: if capsLock: letter = keyCodes[dataList[0]] else: letter = keyCodes[dataList[0]].lower() display.show(letter) message = message + letter elif dataList[0] == 172: # toggle caps lock capsLock = not capsLock if capsLock: display.show(Image.ARROW_N) else: display.show(Image.ARROW_S) elif dataList[0] == 242: # backspace display.show(Image.ARROW_W) message = message[:-1] dataList = [] sleep(delay) if button_a.was_pressed(): display.scroll(message) if button_b.was_pressed(): radio.on() # I'm in love with Massachusetts radio.send(message) radio.off() display.scroll('TX') message = '' display.clear()
Inputting messages is relatively slow. Letters will flash on the micro:bit display. The caps lock key toggles case, but the shift key does not work. If you make a mistake, press the backspace key, which will delete the last character.
Press button A on the micro:bit to see the message, and button B will wirelessly send the message. This will also delete the message because a good spy would cover their tracks, right?
Sometimes it needs a reset when powered on, so if it doesn’t work the first time, press the reset button on the back of the micro:bit and see if you can sort it out.
If you make any improvements, please let me know. I would be very happy if you could like my blog or my YouTube channel.