DIY Programmable 6-Key Keyboard (DigiSpark)

38,108

134

36

Introduction: DIY Programmable 6-Key Keyboard (DigiSpark)

In this Instructables i will use a DigiSpark with a CD4021 Shift Register and read 6 mechanical switches.

Depending on the switch pressed, the DigiSpark will send some key strokes back to the PC. Making a sort of a Macro keypad, where we can assign each tactile switches to send key stroke.

Key Features :



• Programmable keys
• Shortcut keys With one press of a button.
• Volume control keys (for windows)

Step 1: Parts List

  • 1x Digispark (Ebay).
  • 1x CD4021 Shift register . ( Ebay)
  • 16 pin IC socket
  • 1x Tactile Momentary Switches (Ebay)

(mechanical keys) (Ebay) (Banggood)

  • 10K resistors. (number of resistors depend on the number of switches used)
  • Micro USB cable or USB-to-USB cable Depends on type of digispark.

Step 2: Tools

  • Soldering iron
  • Breadboard
  • wires
  • jumper wires
  • Prototyping board
  • Wire strippers /cutters
  • USB cable ( depends on the type of the digispark model)
  • Multimeter

Skills required:

  • Basic soldering skills
  • Basic programming skills

Step 3: Digispark (Software Config)

The Digispark is an Attiny85 based microcontroller development board similar to the Arduino line, only cheaper, smaller, and a bit less powerful. IT use the familiar Arduino IDE the Digispark is a great way to jump into electronics, or perfect for when an Arduino is too big or too much.

Specification:

  • Support for the Arduino IDE 1.0+ (OSX/Win/Linux)
  • Power via USB or External Source - 5v or 7-35v (automatic selection)
  • On-board 500ma 5V RegulatorBuilt-in USB (and serial debugging)
  • 6 I/O Pins (2 are used for USB only if your program actively communicates over USB, otherwise you can use all 6 even if you are programming via USB)
  • 8k Flash Memory

Installing the Digispark Drivers

Make sure to use Arduino IDE version 1.6.7 otherwise uploading error will occur.

Watch this video to learn how to install Digispark drivers (That is created by Brainy Bits)

the Best Tutorial that i found.

https://brainy-bits.com/ check their site for more information

And Check this link to learn how to connect and program the Digispark using the Arduino IDE

https://digistump.com/wiki/digispark/tutorials/con...

Libraries

Drivers


Make sure to use Arduino IDE version 1.6.7

Because i got avr errors when uploading the code.

Arduino IDE

Step 4: Connections

Pins Connections (digispark to shift-register)



• Digispark GND -------------- CD4021 GND/VSS
• Digispark 5V/VCC ---------- CD4021 VCC/VDD




• Digispark (P2 , D2) --- CD4021 LOAD / (pin 09 )


• Digispark (P1 , D1) --- CD4021 CLOCK / (pin 10)


• Digispark (P0 , D0) -- CD4021 SER OUT / Q8 / (pin 03)


Tactile Buttons (8 switches)

One leg of the Tactile Switches/ mechanical switch is connected to the 5V line.

The other leg of the Tactile Switches/mechanical switches are connected to pin 1-2-3-4-5-6-7 of the CD4021.

Pins 1-2-3-4-5-6-7 also have some 10K resistors connected to ground for switch pulldowns.

Look At the circuit layout for further clarifications.


Step 5: Soldering

The parts were soldered on piece of perfboard that will fit in my enclosure .Just follow the circuit diagram in the above step.

Step 6: Enclosure

The plywood parts were laser cut and I used wood glue to glue the parts to form the enclosure.

Step 7: The Test Code

Check step 4 to learn how to install the libraries.

Before verifying the code , change the board to Digispark default .this will the ensure that the Digikeyboard.h is present in Arduino IDE . otherwise the digispark libraries are not present in the IDE even though its installed properly.

Each button has its unique binary value depending on the CD4021 pin , therefore to find out which is which upload this test code to the digispark

open the notepad and press the buttons and check the output.

Step 8: Code ( EASY TO TEST WITH THIS LIBRARY)

Upload this code.

To have the DigiSpark act as a Keyboard, we will be using a library called “DigiKeyboard” created by DigiStump.

Check the PDF file to find out the Arduino key word for each keyboard key.

To send a key stroke this command is used.

DigiKeyboard.sendKeyStroke();


To print something like "hello" this command is used.

DigiKeyboard.print ("Hello");


To put a delay this command is used:

DigiKeyboard.delay();


To press two keys at once :

separate the two key commands with a comma

eg:

DigiKeyboard.sendKeyStroke(KEY_C , MOD_CONTROL_LEFT);//copy shortcut (ctrl +v).
DigiKeyboard.sendKeyStroke(KEY_L , MOD_GUI_LEFT);//windows lock shortcut  (windows logo key + L)
  • On the keyboard the key that is pressed second should come before the comma. for example in the copy shorcut the "C" key should be before "control" key. But on the keyboard it should be "ctrl" key then the "c" key.

To press three keys at once:

separate two keys with a comma and the third command with a

DigiKeyboard.sendKeyStroke(KEY_ENTER , MOD_CONTROL_LEFT | MOD_SHIFT LEFT); 

(Ctrl + Shift + Enter)

  • Always the the last key that should be pressed must come before the comma. In the above case "ENTER" must come before the comma.



To only press the windows key:

DigiKeyboard.sendKeyStroke(0, MOD_GUI_LEFT );

To execute a command with a single press:

To open "CMD" in administrator mode , assign a key to this code and change the binary value .

if (RegisterValue == B10) 

DigiKeyboard.sendKeyStroke(0,MOD_GUI_LEFT ); // press the windows key
DigiKeyboard.delay(1000); // wait a second
DigiKeyboard.print("cmd");
DigiKeyboard.delay(1000); // wait a second
DigiKeyboard.sendKeyStroke(KEY_ENTER,MOD_CONTROL_LEFT | MOD_SHIFT_LEFT ); // Ctrl+shift+enter
DigiKeyboard.delay(1000); // wait a second
DigiKeyboard.sendKeyStroke(KEY_ARROW_LEFT );
DigiKeyboard.sendKeyStroke(KEY_ENTER );

UsefulWindows 10 shortcut keys

After uploading is done , remove the USB cable and plug it back again.

If you receive and error saying the USB is not recognized try unplugging and plugging back it again and while its initializing press any key repeatedly until it works.

Step 9: Code ( With Different Library) #USE THIS #

Download and install this (Adafruit-Trinket-USB) library to your Arduino IDE.

upload the code and change according to your needs.

when using this code no need to press a key when plugin in the cable.

Useful key codes

Example code: This replicate the exit action with a button.

// EXIT APPLICATION(Alt + F4) 

TrinketHidCombo.pressKey(KEYCODE_MOD_LEFT_ALT, KEYCODE_F4);

TrinketHidCombo.pressKey(0, 0); // releasing keyboard.

Attachments

Step 10: Volume Controls (optional)

To use Volume Control

Download and install this library (Adafruit-Trinket-USB) in your Arduino IDE.

upload this code and change the register value to match the button.

TrinketHidCombo.pressMultimediaKey(MMKEY_MUTE); // mute

TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_UP); // volume up

TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_DOWN); // volume down

Step 11: Final Thoughts

Thanks for reading! I'd love to hear your thoughts.

2 People Made This Project!

Recommendations

  • Rocks, Gems, and Stones Speed Challenge

    Rocks, Gems, and Stones Speed Challenge
  • Space Contest

    Space Contest
  • Micro:bit Contest

    Micro:bit Contest

36 Comments

0
monokai
monokai

5 months ago

Hi, I'm working on a 30% keyboard - and I was wondering if I could use this idea, with additional shift register (so two CD4021BE, daisy chained) to drive switch matrix 3x10.

I am wondering if I need additional resistors there for switch pulldowns?

schematics.png
0
davidlivingston116
davidlivingston116

Reply 4 months ago

Hey,
i cant seem to find CD4021 Shift register here in India.
Can i use N74HC164N PDIP from Texas Instruments as an alternative ?
Thanks in advance.

0
tharindurc
tharindurc

Reply 5 months ago

Hi, I think it would be possible. But I would suggest using QMK firmware instead because you would not need any shift registers or any resistor the just the matrix would be sufficient. But you would need to change the board. (https://bit.ly/3n6nAez)

Even I build mine using QMK firmware
https://www.thingiverse.com/thing:4134988

With this, you could build the firmware and upload file to it.
https://kbfirmware.com/

With this, you could generate a keyboard layout and copy the layout and paste in the above link.
http://www.keyboard-layout-editor.com/

This will be helpful to create the matrix
http://blog.komar.be/how-to-make-a-keyboard-the-ma...

0
davidlivingston116
davidlivingston116

4 months ago

Hey!
I can't seem to find the CD4021 Shift Register here in India.
Can i use 74HC165by Texas Instruments instead.
Thanks in advance.

0
Omnipotenti
Omnipotenti

Question 2 years ago on Introduction

Hi Tharindurc,
I'm looking to build something similar to this and this guide has been super helpful. I want to use 8 switches (using PI-1 through to PI-8). Would using PI-8 work or is this reserved for something else? I notice you mention that the switches should be connected to pins 1-7 with no mention of the 8th pin on the CD4021.

0
tharindurc
tharindurc

Answer 2 years ago

Hi Omnipotenti
PI-8 is not reserved for anything, it will work just fine.I could not use it because i was not able to read its binary value.That is the reason i kept it out.

Try this link,You might need a arduino uno or something similar to read the bin value
https://www.arduino.cc/en/Tutorial/ShiftIn

0
prabbit237
prabbit237

7 months ago

BTW, this is more a generalized comment about coding than specific to this project. With any microcontroller, flash is at a premium but even more so on the attiny85's. I've learned some tricks to try and tweak out a few bytes here and a few there. In this case, the code is pretty small so you have plenty to spare. Also this code doesn't have to be blazingly fast so speed isn't an issue, either. But when you're doing the if statements, two things can help with speed and with size:

Speed: Put the most commonly used cases first and use ELSE statements. So if the B10 key is used most, put it first. But this doesn't help if it still has to check ALL of the others every cycle. So if 90% of the time, B10 is the one that matched, you don't need/want to check B1, B100, etc. To avoid that, abort the loop once a match is found. And the two methods to do that also help with code size:

Speed-method one: Use if...else... instead of a bunch of if's by themselves. So it'd be:

if (RegisterValue == B1000000) {
DigiKeyboard.sendKeyStroke(KEY_C, MOD_CONTROL_LEFT ); //COPY SHORTCUT (ctrl+c)
} else {
if (RegisterValue == B1000) {
etc.......

But those nested if...else... statements get ugly FAST, even with indentions. So.......

Speed-method two: switch...case... statement.
switch (RegisterValue) {
case B1000000:
DigiKeyboard.sendKeyStroke(KEY_C, MOD_CONTROL_LEFT ); //COPY SHORTCUT (ctrl+c)
break;
case B1000:
etc......

In either situation, once it finds a match, it quits checking other possibilities so you do want to possibly re-order them. But keep in mind, if you managed to hit two buttons at pretty much the same time, then it wouldn't trigger on both (which may be desirable.)

Size: These two methods actually make for smaller code as well. Your original code uses 3498 bytes. The if...else... uses 3466 bytes and the switch...case... (leaving off the "default" case as there's no need for it) uses 3468. Sometimes those few bytes makes the difference between "AUGH!!! It's too big" and "Whew, just barely fits."

But it's still a great project that I ran across when looking at ways of doing the same thing but with an IR remote (it's using the same library to send the keystrokes to a raspberry pi but just a different method of input.)

It can also be used as a practical joke or a "haunted device" by having the Digispark generate its own keystrokes more or less randomly or every so often it "prints" out a msg like "Help! I'm trapped inside the computer!!!!" *evil grin*

0
prabbit237
prabbit237

7 months ago

BTW, this is more a generalized comment about coding than specific to this project. With any microcontroller, flash is at a premium but even more so on the attiny85's. I've learned some tricks to try and tweak out a few bytes here and a few there. In this case, the code is pretty small so you have plenty to spare. Also this code doesn't have to be blazingly fast so speed isn't an issue, either. But when you're doing the if statements, two things can help with speed and with size:

Speed: Put the most commonly used cases first and use ELSE statements. So if the B10 key is used most, put it first. But this doesn't help if it still has to check ALL of the others every cycle. So if 90% of the time, B10 is the one that matched, you don't need/want to check B1, B100, etc. To avoid that, abort the loop once a match is found. And the two methods to do that also help with code size:

Speed-method one: Use if...else... instead of a bunch of if's by themselves. So it'd be:

if (RegisterValue == B1000000) {
DigiKeyboard.sendKeyStroke(KEY_C, MOD_CONTROL_LEFT ); //COPY SHORTCUT (ctrl+c)
} else {
if (RegisterValue == B1000) {
etc.......

But those nested if...else... statements get ugly FAST, even with indentions. So.......

Speed-method two: switch...case... statement.
switch (RegisterValue) {
case B1000000:
DigiKeyboard.sendKeyStroke(KEY_C, MOD_CONTROL_LEFT ); //COPY SHORTCUT (ctrl+c)
break;
case B1000:
etc......

In either situation, once it finds a match, it quits checking other possibilities so you do want to possibly re-order them. But keep in mind, if you managed to hit two buttons at pretty much the same time, then it wouldn't trigger on both (which may be desirable.)

Size: These two methods actually make for smaller code as well. Your original code uses 3498 bytes. The if...else... uses 3466 bytes and the switch...case... (leaving off the "default" case as there's no need for it) uses 3468. Sometimes those few bytes makes the difference between "AUGH!!! It's too big" and "Whew, just barely fits."

But it's still a great project that I ran across when looking at ways of doing the same thing but with an IR remote (it's using the same library to send the keystrokes to a raspberry pi but just a different method of input.)

It can also be used as a practical joke or a "haunted device" by having the Digispark generate its own keystrokes more or less randomly or every so often it "prints" out a msg like "Help! I'm trapped inside the computer!!!!" *evil grin*

0
prabbit237
prabbit237

7 months ago

I don't know if you can edit these instructables after they are posted but there's an error in:

"Pins 1-2-3-4-5-6-7 also have some 10K resistors connected to ground for switch pullups."

The resistors would be "pulldowns" as they are pulling the level down to ground (when the key is pressed, it then pulls it back up to 5v.)

0
tharindurc
tharindurc

Reply 7 months ago

Thanks for pointing that out. I have edited it...

0
TiltedBretzel_
TiltedBretzel_

3 years ago

The program is working well.
If you have issues with a "const unsigned char ascii_to_scan_code_table" compiling error, just edit the "scancode_ascii_table.h" like there : https://github.com/digistump/DigistumpArduino/pull... , it makes it working for me.

Good job for the rest by the way ! and Thanks !

0
Wake.Array
Wake.Array

Reply 2 years ago

I looked in the comments hoping for an answer to this and this comment did not disappoint. +1

0
tharindurc
tharindurc

Reply 3 years ago

Thanks for pointing that out .

0
xmzxmlx
xmzxmlx

Question 2 years ago

hi, i have try pressing any button after plugin the usb but it still unrecognized, while using other code i just run with out any problem

0
tharindurc
tharindurc

Answer 2 years ago

Hi.
This happens when you are using digikeyboard library?
I really dont what is problem with the library.That is the reason why i included trinket which has more keycombos than the other.Use trinket library instead.

0
xmzxmlx
xmzxmlx

Reply 2 years ago

hi, thank for the reply
i have try using the trinket library, it now recognized as hid device but it still cannot detect any button press

0
tharindurc
tharindurc

Reply 2 years ago

Cannot detect any buttons as in you cant see what is pressed.were you able read the binary values?

0
xmzxmlx
xmzxmlx

Reply 2 years ago

yes, i already try the testing for binary value code but it fail to detect the usb

0
tharindurc
tharindurc

Reply 2 years ago

I think it is something to do with shift register.Have you tried changing the shift register?
Im not really sure whats wrong with this, since i never encountered such problem with my build