- Arduino Micro Keyboard Tutorial
- Arduino Pro Micro Keyboard.h
- Arduino Usb Keyboard Input
- Arduino Micro Keyboard Download
- Arduino Micro Keyboard Driver
First of all you need to set your arduino to DFU mode. You can do this by connecting the 2 pins in the image for a split second (while connected to your pc). Then, you need to upload the keyboard.hex file through flip. Press ctrl+u and click on 'open'. Install Atmel flip which will allow you to put the arduino-keyboard-0.3.hex file onto the arduino. Arduino to Keyboard: Once Atmel is installed and your board is plugged in, load Atmel up and click on the computer chip icon below the file button, select the processor of the board you are using. In my case it was a ATmega16U2.
Hello, I posted earlier about another music project but after several days of trying to fix code I wanted to put it on hold for a while. I took apart one of my electronic keyboards which had midi out but I want to make it as diy as possible. So I took the keys out and left the matrix chip and other things away.
Now I have figured out how many columns and rows it has inside the keyboard matrixBut the problem is the library im using seems to only accept one number into the key mapping
Im using Pro Micro cheap china copy
My keyboard has 49 keys8 rows and 7 columns (7th is just one Note)it turns into 15 wires Connected to my Arduino pro micro (you can find pin-in inside code)
Now my problem is I don't know how to name code the keys for the 'char hexaKeys' since its such a big number on these keys
First I tried to name them with C1, C1# // D2, D#2, and so onBut I realised it didn't accept more than one letter into the mappingSo I tried to do the alphabet and numbers but its not enough for 49 keys
'char hexaKeys[ROWS][COLS] = {{'A', 'B', 'C', 'D', 'E', 'F', 'G'},{'H', 'I', 'J', 'K', 'L', 'M', 'N'},{'O', 'P', 'Q', 'R', 'S', 'T', 'Y'},{'X', 'Z', '1', '2', '3', '4', '5'},{'6', '7', '8', '9', '0', '6', '7'},{'0', '1', '2', '3', '5', '6', '7'},{'0', '1', '2', '3', '5', '6', '7'},{'0', '0', '0', '0, '0', '0', '0'},'
Then I started thinking maybe I have to write another code, or can I somehow convert this hex into something else that can fit characters into the code? I want to turn this later on into midi events (usb or analog)
I started thinking more while writing the topic and I tried to put the notes into the graph in the code comments and its like my brain hit a wall and I realised I am going to deep and 'entering the matrix' .(As you can see in the code with hexakeys its all a mess but thats not the trouble right now)
Maybe im misunderstanding this library?
Music aspect will have to be solved later anyway. But if I at least could give the matrix keys a name I could later transfer them to notes with the help of serial monitor. Appreciate all help and insight
library: https://github.com/Chris--A/Keypadexample: https://github.com/Chris--A/Keypad/blob/master/examples/CustomKeypad/CustomKeypad.ino
I’m a self-confessed keyboard nerd and got a hold of this keyboard for the keycaps off of a friend. Initially I’d thought they would be cherry compatible, but unfortunately, they are not. So rather than butchering a perfectly good keyboard, I wanted to make it USB compatible. Please bear with me, this is the first time I’ve done any projects interfacing with unknown hardware, or even with an Arduino.
Resources
Here’s the GitHub repository for the current code, and all the circuit diagrams I could find. There are a few issues with the layouts of each of those, however:
- A couple of the matrix values in the diagrams are swapped
- The pins for the logic chips don’t line up to the rows and columns
- To get the LEDs to enable, you should ground the LED pins, they are already supplied 5V
Hardware
The ATmega32U4 was chosen for a few reasons:
- It can act as a USB device
- It is compatible with the Arduino programming framework, and there’s plenty of resources and a good community behind it
- Another project from Tynemouth Software doing the same thing is using it, so I know it could be done.
Circuit diagrams
These were collected online from various sources, the first of two contains more information, the second is more basic and easier to understand at a glance.
Note that the rows are organised differently in the two diagrams and there is some disagreement between the locations of “I” and “9”.
IC Diagrams
- IC1 : 74LS163 4 bit binary counter
- IC2 : 74LS251 8 bit (row) counter
- IC3 : SN7445 8 bit (column) counter
- IC4 : 74LS30 8 input NAND gate
Kit needed
- Multimeter
- Oscilloscope
- Ardunio pro micro (5v 16MHz), I used the cheap ones from eBay for ~£3 delivered
- Breadboard and breakout leads
- BBC Micro keyboard
How it works
The keyboard has some integrated logic on board, but as a basic breakdown a few things happen (as if it was still in the main box):
Arduino Micro Keyboard Tutorial
- The keyboard scans at 1MHz, this clock signal comes from the BBC Micro’s slow bus into IMHZ.
- A key-press is detected and sets CA2 to high.
- The BBC Micro receives the keypress signal and pauses the scanning of the keyboard matrix by setting KB EN to high.
- The rows and columns are checked by the BBC Micro by binary counting the row and col pins
- W (PA7) goes high to indicate the correct row and column combination is found
- Searching the matrix is stopped, KB EN is set to low and the keyboard resumes scanning
There is one exception, which is the break key that is a directly wired switch, that avoids the logic designed to perform soft/hard resets of the BBC micro.
There is a more detailed explanation of the whole system and keyboard available here.
Pin mapping
BBC Pin | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Function | Ground | Break | Clock | Row A | Row B | Row C | Col A | Col B | Col C | Col D | W | LED0 | CA2 | +5v | LED1 | LED2 |
Arduino Pin | GND | A3 | 9 | 6 | 7 | 8 | 5 | 4 | 3 | 2 | A1 | 16 | 10 | VCC | 14 | 15 |
Pin mappings for the BBC are from the top left to right, with the keyboard face up with the pins facing away.
The Code
So there are a few things we need to do here; generate a clock, listen for a keypress, scan the keyboard matrix, find out when we have the right combination of rol and col, and finally convert the (row, col) value to the correct character.
Clock generation
First thing’s first, supply the keyboard with ~5v from the VCC pin and generate a 1MHz clock on pin 9.
Put simply, this enables the fast PWM mode on pin 9 for a 1MHz signal, further details can be found in section 14.8.3 of the ATMega manual.
LED Control
The LEDs on the main motherboard are already powered and need to be connected to ground to get to work. Setting the LED pins to output mode, and using the digitalWrite function to turn them on (LOW) and off (HIGH). Currently, the LEDs are mapped in the code to display keypress events and when the correct key has been found from scanning the rows and columns.
‘High’ and ‘Low’
Early on, it became clear that the digital read mode on the Arduino would not be suitable as it uses a +5v signal for high, where the keyboard was returning +1.8-2.2v for high. So to compensate, an auto-adjusting sensor for each of the input pins using the analogue input.
Each input pin was set to an AnalogInput mode and checked every cycle. The low value was stored as it would drift. To ignore the drifting and nose on the pin, a threshold was added to ensure the readings for high were not false positives.
Arduino Pro Micro Keyboard.h
Enter the matrix
Once a keypress event is detected by a ‘high’ on CA2, KB EN is set to pause the scan high and start searching the matrix.This is done is by counting in binary across the logic chips e.g. 0 = 000, 1 = 001,… 4 = 100.
To encode this information, set the lines you want to count with to digitalWrite(high) and then check to see if W has gone high, indicating that you have found the correct row & col value.
Arduino as a keyboard
Arduino has a great (but limited) keyboard library, that I’ve used here to turn the device into a USB keyboard.
It allows the device to send ASCII characters in the same way a keyboard would. It can be sent as a quoted character, ASCII binary, base 10 or hexadecimal.
Keypress to character
The next step is to map out the keyboard matrix into numerical matrices with the ASCII characters for three states: lower case, upper case and shifted. Once we have the correct mappings for these, they are converted to the integer values in ASCII using this very helpful tool.
Lower case matrix
Upper case matrix
Shift case matrix
The negative numbers are not valid ASCII characters and are used to represent special cases:
- -99 is the shift lock key and requires special handling
- -2 = go to upper case matrix
- -1 = go to lower case matrix
- any other negative are unmapped keys, in this case, the startup option switch and Copy
Keyboard Layout assumptions
In order to get the key mapping to work, it is necessary to not send the data about the state of the shift key. This is done as I found that assumptions are made about the key mapping (at least on Linux), so “Shift + 3” is the “£” key on a UK layout, however, on the BBC KB this is the “#” character, so sending “Shift + 3” would print the “£” character.
So send “#” and problem solved, right? Well, no. Even though the correct ASCII code for “#” would be sent, as the shift key would also be held, the assumption is that it should be remapped this to the shifted version on a UK keyboard which is “~”.
So in order to send the correct characters, I had to withhold the shift status and store it locally on the Arduino to modify the keypress.
[0, 1, 2] != [0, 1, 2]
After scouring over the circuit diagrams, I had assumed that the layout of the rows and columns would be in a logical order. However, after a long and frustrating time, it appears that the layout of the rows does not follow my assumed logical mapping. After looking at it, this is clearly done to keep the trace layouts simple and efficient. (However, be wrong and just have some wires crossed.) The row order that works for me is :
Decimal | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Expected | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
Actual | 000 | 011 | 101 | 001 | 110 | 010 | 100 | 111 |
Shift & Ctrl
Currently, my ‘Shift’ and ‘Ctrl’ buttons are not working. Unfortunately, it looks like the whole row of keys is out of commission. I’ll get back to this where I have more time, the rest of the row should be a row of selector switches, but this isn’t included on this keyboard model.
Irregular keys
Arduino Usb Keyboard Input
There are quite a few keys on this keyboard that are not in use anymore:
- F0 - I’ve mapped to F10
- Shift Lock
- Copy
- Break
The break key is an interesting one and is wired independently to the keyboard. It is intended to be used to warm or cold restart the machine. I’m currently thinking I should map this and the ‘Copy’ key to “Ctrl + c”.
Shift lock has been implemented, by storing the value on the Arduino and passing the appropriate shifted ASCII code. F0 has been mapped to F10.
Arduino Micro Keyboard Download
Future work
Arduino Micro Keyboard Driver
- Make the keyboard QMK compatible. However, I’m not sure if this is possible
- Play the BBC Micro keyboard startup sound when plugged in/turned on
- Improve on the ‘trickery’ for the shift keys, I’m not a fan of how it’s currently done.
- Speed up the key scanning, it’s horribly slow
- Improve on the key repeat mechanism when a key is held down, and add a delay before the first repeat and a shorter delay for the second+ repeats.
- Handle multiple key presses at the same time, I believe this keyboard has a 2/3 key rollover.
- Code in the 8 bit startup options switch