Read a PS/2 keyboard on a BBC micro:bit

What you’ll learn

  • That computer keyboards aren’t just switches – they need power to make them work
  • They comprise a matrix of buttons connected in rows and columns
  • Computers don’t read your keypresses directly – the keyboard contains a circuit board that does that
  • The keyboard sends keypresses to the computer as a stream of serial data – in effect numbers
  • Old-fashioned PS/2 keyboards send a code when you press a key and another when you release it
  • PS/2 keyboards aren’t, strictly speaking, just input devices. They also receive data from computers, for example to light the CAPS LOCK light output

Background

This is a testament to the power of ignorance. If you don’t know you can’t do something, sometimes you end up being able to do it.

For years I’ve wanted to connect a normal computer keyboard to a BBC micro:bit to make radio messaging and cryptography easier to use. I’ve seen, and indeed made myself, similar things on an Arduino, using libraries designed to read the subtle data coming from a PS/2 keyboard, frighteningly complex libraries in C++ that unpack every transition of every pulse of every bit of digital data.

Well, that’s not how I roll.

Previously I connected a thermal printer straight to a micro:bit and threw some serial data at it, and it worked first time, printing my message.

I never expected my home-made key-pad matrix, coded in utter ignorance, to work. But it did. First time.

Sometimes it’s helpful not to be fettered by knowledge and precedent, though not, I hasten to add, if you’re flying a plane, performing surgery or indeed running a country.

So I decided to take that approach to my micro:bit PS/2 keyboard problem.

What is a PS/2 keyboard anyway?

PS/2 keyboards are the old-fashioned type that came before USB – they often have round plugs, usually encased in purple plastic. (PS/2 mice tended to have green plugs.) They’re not especially easy to buy, at least not new, but people often throw them out, as we’ll see…

They’re just a matrix of buttons attached to a small controller running at 5 volts that turns key presses into serial data. Ok, the protocol is pretty horrible… an 11-bit word sent at anything between 10 and 16.7 kHz and comprising:

  • 1 start bit (always 0)
  • 8 data bits (least significant bit first)
  • 1 parity bit (odd parity)
  • 1 stop bit (always 1)

So I decided to ignore all that. I was walking the dog one day and found a PS/2 keyboard dumped at the side of the road, helpfully with the plug already cut off, and the plug also by the side of the road.

This was a sign.

The investigation begins

matrix inside a computer keyboard

Inside a computer keyboard

I took it home and opened it up. You can see in the picture above how the keys comprise two layers of plastic film that are pressed together to complete a circuit. The keys are arranged in a matrix, a grid of rows and columns.

In the corner you can see the controller printed circuit board that contains the caps, num and scroll lock LEDs as well as the electronics that convert keypresses into a kind of serial data sent down the cable to the PC.

keyboard LEDs and membrane

keyboard LEDs and membrane

I hoped the controller PCB would helpfully show me what each coloured cable did. (There’s no standard for PS/2 cable colours).

detail of keyboard control PCB

detail of keyboard control PCB

reverse of keyboard control PCB

reverse of keyboard control PCB

A few capacitors, LEDs, and an integrated circuit hidden under a blob on the back, and some labels, but alas nothing to identify the purpose of each wire going out to the plug. Even knowing the manufacturer and model number was no use either. Luckily, I still had the severed plug, so I was able to figure out that for this particular Dell keyboard:

Pink = 5v
Black = GND
White = Data
Brown = clock

5v. Hmm, the micro:bit supplies only 3v. Ignoring that, I connected the black wire to micro:bit GND pin and the pink to the micro:bit 3v pin. The LEDs lit up to show the keyboard was doing its power-on-self-test. The NUM LOCK light even lit (but not caps lock, I discovered that’s done in software by PCs, which send a signal back to the keyboard!)

So you can power a PS/2 keyboard off a micro:bit 3v supply – useful! No external power supply needed.

Now, what if I just ignore the clock wire, and pretend that the PS/2 keyboard is just sending serial data? We can read serial data on a micro:bit, I just need to know the Baud rate (the speed at which the data is being sent). That 10 to 16.7 kHz range sounds a bit scary, I tried a few different numbers and found that using 10,000 Baud I managed to get some sensible looking data from this program, with pin 1 connected to the white keyboard data wire and GND connected to the black keyboard ground wire, flashed onto a micro:bit using the online editor.

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

while True:
    if uart.any():
        data = bytearray(1)
        uart.readinto(data, 1)
        display.scroll(data[0])

Pressing the letter Q, for example consistently produced 139, 248, 139.

Pressing A produced 142, 248, 142.

I knew from my reading (see, you do need a bit of knowledge) that PS/2 keyboards send a code when you press a key, then send a release code when you let go. So 139, 248, 139 really means ‘Q pressed’ ‘released Q’.

So all I needed to do was sniff the code for every key I was interested in and create a dictionary to look up the codes and turn them into letters. I’ve only bothered with the alphabet, numbers and some very basic punctuation so far, but I have implemented my own caps lock and backspace. (The caps lock light doesn’t come on, but one day…)

Key codes for other keyboards will probably vary, so use the sniffer program to make your own list if needed. You may also need to use a different Baud rate, but 10,000 worked for me with this Dell.

Secret radio message communicator project

Let’s put this new-found ignorance to use by building a super secret agent communicator! No-one will see you lurking in the bushes with a micro:bit and mahoosive Dell PS/2 keyboard you pulled from the trash!

Put this program on 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 code below. Remember you’ll need to attach pin 1 on the micro:bit to your keyboard’s data wire – mine was white but yours may not be. Also connect your micro:bit 3v pin to the keyboard’s power wire (pink in my case) and micro:bit GND pin to keyboard Ground (black on this Dell).

Type your message quite slowly. Letters will flash on the micro:bit display. The Caps Lock key toggles upper and lower case, but the shift key does nothing. If you make a mistake press backspace and it will delete the last character of your message.

Press button A on the micro:bit to review your message, and press button B to transmit it over radio. This also deletes the message because a good spy covers their tracks, right?

Sometimes it needs a reset when you power it up, so if it’s not working first time, press the reset button on the back of the micro:bit and see if that sorts it.

If you make something with this, please let me know and I’d be thrilled if you could credit me, this blog or my YouTube channel.

Enjoy!

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()

You may also be interested in my post on making a your own key matrix using push buttons and a breadboard: http://www.suppertime.co.uk/blogmywiki/2020/08/microbit-computing-fundamentals/

Code can also be found here: https://github.com/blogmywiki/microbit-ps2-keyboard

Posted in Uncategorized | Tagged , , , , | 5 Comments

How the micro:bit helps you understand fundamentals of computing

I’ve made a few projects recently using 4 x 4 membrane keypads with the BBC micro:bit. I made a calculator, then a wireless communicator and most recently I recreated the 1970s game Mastermind.

I thought it might be interesting to focus on how keypads (and by extension, computer keyboards) work and unpack some more of the learning around this. I think this shows how good the BBC micro:bit is understanding how technology works at a very fundamental level, but at the same time being quite simple and accessible, using block coding thanks to Microsoft MakeCode, and simple components thanks to the design of the micro:bit itself.

There are, for example, many Arduino projects for wiring up keypads but they are difficult to program, using C++ in the Arduino IDE which isn’t very child friendly, and yet at the same time using provided Arduino libraries actually shields you from learning what’s going on at a fundamental level.

Here we’ll see how the micro:bit gives you the best of both worlds: a simple, friendly online code editor, and yet you’ll write your own program to scan and interpret keypresses.

While I was waiting for my ready-made keypads to arrive, curiosity got the better of me. I had a breadboard and a bag of around 100 tiny push-buttons and decided to see if I could make my own. I knew keypads were arranged in a grid or matrix, but I was curious to know exactly how they were wired together.

Looking at a circuit diagram of a keypad you can see that the same side of each button, the left side here, is connected together, row-by-row:

In each column the other side of each switch is connected together:

keyboard matrix wiring diagram columns

This gives you 8 wires for a 4 x 4 keypad. That sounds like a lot, but if you connected each key separately to a computer, calculator or microcontroller you’d have 16 wires plus a ground or earth wire connected to each button as well.

matrix inside a computer keyboard

Inside a computer keyboard

A standard computer keyboard contains around a hundred keys, so inside a keyboard these are usually arranged in a matrix as well, perhaps 6 rows of around 15 keys, meaning it needs just over 20 wires, rather than a hundred.

So a matrix is really a very neat way of arranging keyboard inputs on electronic devices.

micro:bit connected to a home-made keypad matrix

Making my own was fun and quite therapeutic! As every column in a breadboard is connected, and I only wanted to connect one side of each column of buttons together, I decided to stagger the buttons across the board. I used jumper wires to make the connections on each row and column. What you can’t easily see is that there are also jumper wires running underneath each button as well.

So, electrically speaking at least, I had created something that was the same as a real keypad matrix, even if I only had 12 buttons not 16.

But how to make it work?

I didn’t realise at the time that there was already a MakeCode extension for matrix keypads, which was lucky really as I had to invent my own way.

I knew some projects used different values of resistors to read pins using fewer than 8 wires, but I wanted to do it using as few components as possible. Using a breakout board on a micro:bit gives you access to extra pins, and I picked the following pins for rows and columns:

I avoided some pins that are also connected to the micro:bit’s own A and B buttons and elements of the LED display, as I want to able to use them in my projects.

Using digital outputs and inputs on micro:bit pins is a simple way of detecting if a circuit has been made, so I created a loop in MakeCode that sends a digital output to each row in turn:

MakeCode blocks to scan one row

If it receives an input on any of the pins connected to the columns, then that means you must have pressed a button and the program responds accordingly, for example by showing a number or letter. The example below shows how the number 3 in my calculator or Mastermind game, or the letters C or Q would be detected in my communicator project:

a keypress is detected

I really didn’t expect this to work – but it did! I didn’t even have to add any code to debounce… it just seems to work!

Whilst making your own keyboard matrix out of buttons is instructive, it is very fiddly and time-consuming, and you can still learn a lot from using a pre-made keypad matrix. All you need to connect one of these to a micro:bit is a breakout board and some male to female jumper wires.

The code is quite simple to understand, and modify to suit whatever project you happen to be making.

What other fundamentals of computing can you expose and teach with the mighty micro:bit?

Posted in microbit | Tagged , | Leave a comment

Mastermind game for micro:bit

Following my calculator and communicator projects, I decided to recreate the classing 70s game Mastermind on the micro:bit.

Mastermind was based on an older game, possibly called Bulls and Cows or Moo! There have been various computer versions of it over the years, and this is mine. It’s based on guessing numbers. Here’s how to play:

  • The micro:bit thinks up a random 4 digit number which you have to guess.
  • Each digit is unique and there are no zeros.
  • You type in your guess and press D.
  • The micro:bit tells you how many bulls you have – a bull is the right number in the right place. Then it tells you how many cows you have, a cow being a correct number in the wrong place. (Sorry about the sexist bovine terminology, but I can’t think of a better short word to explain it – if you can think of a better pair of names, I’d love to change it!).
  • Use deduction (and luck!) to improve your guesses and work out the secret number.
  • When you do guess it, the micro:bit tells you how many turns it took you.
  • If you give up, there is a cheat mode: press buttons A+B together.

The video explains more about how it works but it’s worth calling out two bits of code that I think are moderately neat.

unique number generation code blocks

These blocks create a 4 digit random number string with unique digits. It uses a while loop which keeps executing until the string is 4 characters long. It picks a random number and if that number is not already in the string, it adds it. When the string reaches 4 characters in length the loop finishes.

counting bulls and cows code

This function counts bulls and cows. It uses a for loop. The first character in a string is at position zero, so starting at 0 is fine. It compares each digit in position in your guess with the digit in the same position in the target number. If they match, that means it’s the right number in the right place, which is a bull, so we increase the bull counter by 1.

If it’s not a bull, then that digit may be a cow, so it then checks to see if the string contains that digit. We don’t need to worry that bulls will also be counted as cows as we’ve already excluded the bull in the first part of the if… statement.

The MakeCode project is below if you want to build your own or explore the code and perhaps improve it. See the communicator project for details of how to connect a 4×4 keypad to your micro:bit – you just need the keypad, 8 female to male jumper wires and a breakout board for the micro:bit.

Posted in microbit | Tagged , , | Leave a comment

micro:bit wireless keypad communicator

Learn how computers scan keyboards and make your own wireless texting machine!

Building on my micro:bit calculator project, which uses a 4×4 membrane keypad attached to a breakout board, I made a simple device so you can send and receive text messages over radio using micro:bits.

One of the problems of sending radio messages with a micro:bit is that it only has two buttons, so you have a few choices: encode the message in the code itself, which means you need a computer or mobile device to change the message; use a clunky user-interface to select each letter using lots of button pushes; or you can use Morse code.

Adding an inexpensive 4 x 4 membrane keypad makes messaging much simpler. 16 keys are not enough for the whole alphabet, but if we use a shift key we have 32 buttons, enough for the alphabet and some punctation. We’ll have to spell numbers out, and we can only have upper case letters (or lower case, but not both).

The keypad is attached to the micro:bit via breakout board and some female-make jumper leads like this:

4x4 keypad wiring diagram

The keypad’s rows, its first 4 connections, are wired to micro:bit GPIO (general purpose input-output) pins 0, 1, 2 and 8. I skipped some pins because some are also used for the display and A and B buttons.

The keypad columns are wired to micro:bit pins 13, 14, 15, 16.

4x4 matrix wiring diagram

It works by sending out a digital ’1′ signal on each of the row output pins in turn and then reading the inputs from the column pins.

When you press one of the buttons, you complete the circuit and the signal comes back and can be read on the digital input column pins. This is how pocket calculator, and even computer keyboards work: they don’t have a wire connected to every button, instead they arrange keys in a grid (or matrix) like this, which they read by scanning rows and columns just like we do here. If you watch the program running in the MakeCode simulator you may also be able to see the scanning happenning.

Button A on the micro:bit acts as the shift key to swap between letters. I re-labelled the keypad with some masking tape and a Sharpie so I know which button to press, but in case I make a mistake there’s a backspace key and a space key that don’t require any use of shift, they always have the same function. (I could have used something like T9 multi-tap, but I think this is simpler – if you disagree, try coding your own T9-type text entry!)

Pressing button B transmits the message by radio to another micro:bit, on radio channel 23. It could be picked up by any other micro:bit MakeCode program, or by one running exactly the same code as this.

One thing to note is that the main forever loop has a small pause added. This is to allow time for the micro:bit to stop and process the on radio received block.

Let me know if you make one of these – the parts are not expensive, I bought a 5-pack of the keypads for well under £10. It could make a fun multi-player espionage game, perhaps adding some cryptography and code-breaking. Or you could just use it for socially-distanced messaging, as the range of the micro:bit’s radio is very much more than 2 metres!

.

Update: MakeCode extension

I’ve just discovered from @liou_jj in Taiwan that there’s a MakeCode blocks extension for these kinds of keypads: https://github.com/lioujj/pxt-keypad. I’ve not tried it, but it does look useful as it lets you set your own pin numbers so you can use it with other peripherals or avoid the pins used for buttons A and B or the display. I’d still recommend checking out my code above because it allows you to learn how keyboard scanning works, but an extension like this could make it easier to add keypads to your projects.

Posted in computers, microbit | Tagged , | Leave a comment

micro:bit calculator with external keypad

I learned a lot about how matrix keyboards work in a recent micro:bit project where I made my own out of some buttons and wire.

It’s much simpler, though, to use a ready made one and these 4×4 membrane keyboards were very inexpensive as a 5-pack. I set about wiring them up to a micro:bit and creating a simple calculator program in Microsoft MakeCode.

keypad wiring and layout

The keypad layout is not the same as a normal calculator, which has 7 8 9 in the top row, but it’ll do. I used the A B C D keys for the operators multiply, divide, subtract and add. I used the * button as decimal point and # as the equals key.

The first 4 pins on the keypad are the matrix rows, I connected them to micro:bit pins 0, 1, 2 and 8. (I skipped some pins which are also used for the display.)

The next 4 pins are the columns and I connected them to micro:bit pins 13, 14, 15 and 16.

4x4 keypad wiring diagram

If you have male-female jumper wires you don’t even need a breadboard to connect the keypad to your micro:bit, but you will need a micro:bit breakout board to access the pins.

To use the program, flash it on to a micro:bit. It will only add, multiply, divide or subtract two numbers. Each button press flashes the number on the screen, so pressing 2 2 will enter the number 22.

The program stores this as a text string, and when you press an operator key it assigns the number to variable a (also a text string).

When you press equals, it assigns the second number to variable b and then the calculate function converts the a and b strings to numbers using the parse to number block and carries out the appropriate calculation. If you miss the answer scrolling across the screen, you can press equals again to see it. Press button A on the micro:bit to clear, and button B shows you the currently stored calculation without actually giving the answer.

Here’s the code – it’s quite long but uses functions to try and make it more readable. The longest function is scanKeys which sends a digital signal out on each row in turn and reads the column pins to see if a connection has been made. I really didn’t expect this to work, but it seems to and doesn’t even require any de-bouncing.

Can you think of any other uses for a 4×4 keypad on a micro:bit? Some ideas floating round my head:
- noughts and crosses game
- Simon memory game
- controlling a robot
- making a micro:bit version of an early computer like a Kim-1 or an Acorn System 1
- electronic door lock
- alphabetical character entry using shift keys or 2 micro:bits and keypads for a radio / cryptography messaging project

.

Update: MakeCode extension

I’ve just discovered from @liou_jj in Taiwan that there’s a MakeCode blocks extension for these kinds of keypads: https://github.com/lioujj/pxt-keypad. I’ve not tried it, but it does look useful as it lets you set your own pin numbers so you can use it with other peripherals or avoid the pins used for buttons A and B or the display. I’d still recommend checking out my code above because it allows you to learn how keyboard scanning works, but an extension like this could make it easier to add keypads to your projects.

Text communicator

If you like this project, try my wireless text message communicator next!
micro:bit text communicator

Posted in computers, microbit | Tagged , | 2 Comments