소스파일(아두이노코드, 3D모델파일)을 상업적 이용을 금하며, 모든 권리는 뉴틀킴에서부터 나옵니다.
안녕하세요. 뉴틀킴입니다.
이번에 만든 디바이스는 "3D Printed 9KEY 매크로 키보드" 입니다.
Atmega32u4(아두이노 마이크로)를 활용하여 저번에 만든 볼륨 컨트롤러와 1Key 키보드를 통합하였습니다.
여기서 키의 숫자를 늘리면 하면 n키 키보드가 됩니다.

제작방법
준비물
- 3D 모델파일 다운 :
- Stand part (Opt.)
- 아두이노 소스코드 :
- 전자 부품 :
(1) Arudino Micro x 1
(2) Rotary Module Module x 1
(3) Cherry Switch x 9
(3) Diode(1N4148) x 9
(4) Knob x 1 (Opt.)
먼저 전자부품의 CAD 데이터를 참고하여 3D모델링을 진행합니다. 이번에 설계한 Macro Keyboard 는 Main_body, Top_cover, AngleStand(Opt), Keycap(Opt), Knob(Opt) 총 3개의 주요파트로 구성되어 있습니다. (Opt : Optional)
3D데이터는 위 링크에 들어가셔서 다운가능합니다.


3D모델파일이 준비가 되었으면 3D프린터로 출력합니다. 이번에 제작하는 디바이스는 좀더 제품과 유사하게 제작하고 싶어서 레진을 활용한 SLA 3D프린터(Form2 & Form3)를 사용하였습니다.
3D프린팅 파트들도 다 준비되었으니 이제 전자회로 작업을 진행합니다. 이번에는 엔코더 Unit을 사용하지 않고 모듈을 사용하여 회로가 심플하게 나왔습니다. 키마다 다이오드를 사용하는이유는 고스트키 현상을 막기위해 필요합니다. (고스트키 : 여러개의 키가 눌려질때 어떤키가 인식이 안되거나 다른키가 눌린것으로 인식)

위 그림처럼 회로를 구성하였습니다. 아두이노 마이크로의 D2(CLK), D3(DT)은 외부인터럽트(CHANGE)를 사용하여 엔코더의 변화를 센싱하고, D4핀은 엔코더의 스위치에 연결합니다.

위 회로도대로 납땜작어블 합니다.
D5 ~ D9 키보드 출력핀, A1, A2 는 입력 핀(내부저항 사용)입니다.
이번 프로젝트는 앞선 프로젝트에 연장선의 성격이 강하므로 브레드보드 단계 테스트는 생략합니다. (과거의 나를 믿으며)
이번에도 볼륨컨트롤러를 사용하니까 아두이노 예제에서 제공하는 keyboard.h 원시 헤더파일을 수정합니다. (이유는 이전글 참고)
mac 기준으로 볼때 파인더 -> 폴더로 이동 -> /Users/xxx/Library/ -> Arduino15 -> libraries -> Keyboard -> src 에 들어가서 위 파일을 덮어 씌웁니다.

키 맵핑
아래 이미지처럼 매크로 키를 수행하는 코드를 제작하였습니다.

소스파일
/*
Newtle Kim Keyboard Project #3
Macro Keyboard for MAC
Reads an digital input on pin 4 for Encoder Switch
Connect the encoder CLK to pin 2, DT to pin 3.
This example code is in the public domain.
Please refer to the video below for details on how to make it in detail.
https://www.youtube.com/@newtlekim/videos
3Dmodeling :
All designs and sources are open, but be sure to list the sources.
Source : https://www.youtube.com/@newtlekim
Put the keywords below in parentheses.
Keyboard.release()
KEY_LEFT_GUI : ⌘ Command
KEY_LEFT_CTRL : ⌃ Control
KEY_LEFT_ALT : ⌥ Option
32 : Space
KEY_LEFT_SHIFT : Shift
KEY_CAPS_LOCK : Capslock
KEY_TAB Tab : Tab
KEY_ESC : ESC
*/
#include <Keyboard.h>
const uint8_t Keyboard_Volume_Down_MUTE = 0x7f;
const uint8_t Keyboard_Volume_Up_RAW = 0x80;
const uint8_t Keyboard_Volume_Down_RAW = 0x81;
#define CLK 2 // CLK D2
#define DT 3 // DT D3
#define SW 4 // Encoder Switch D4
int counter = 0;
int currentStateCLK;
int lastStateCLK;
void setup() {
Keyboard.begin();
pinMode(A1, INPUT_PULLUP);
pinMode(A2, INPUT_PULLUP);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(CLK,INPUT);
pinMode(DT,INPUT);
pinMode(SW,INPUT_PULLUP);
lastStateCLK = digitalRead(CLK);
attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);
}
void loop() {
int sensorVal = digitalRead(SW);
if (sensorVal == LOW) {
detachInterrupt(0);
detachInterrupt(1);
Keyboard.pressRaw(Keyboard_Volume_Down_MUTE);
delay(500);
Keyboard.releaseRaw(Keyboard_Volume_Down_MUTE);
attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);
}
//9 Key : 강제종료
digitalWrite(5, LOW);
if (digitalRead(A1)) Keyboard.releaseAll();
else{
Keyboard.press(KEY_LEFT_ALT); // ^
Keyboard.press(KEY_LEFT_GUI); //Command
Keyboard.press(KEY_ESC); // ESC
delay(500);
}
digitalWrite(5, HIGH);
digitalWrite(6, LOW);
// 8 key : 화면 캡쳐 프로그램 실행
if (digitalRead(A1)) Keyboard.releaseAll();
else{
Keyboard.press(KEY_LEFT_GUI); //⌘
Keyboard.press(KEY_LEFT_SHIFT); //shift
Keyboard.press('5'); // 5
}
// 4 key : Mac 잠그기
if (digitalRead(A2)) Keyboard.releaseAll();
else{
Keyboard.press(KEY_LEFT_CTRL); // Ctl
Keyboard.press(KEY_LEFT_GUI); //⌘
Keyboard.press('q'); // ESC
delay(500);
}
digitalWrite(6, HIGH);
digitalWrite(7, LOW);
// 7 key : 창 화면 캡쳐
if (digitalRead(A1)) Keyboard.releaseAll();
else{
Keyboard.press(KEY_LEFT_GUI); //⌘
Keyboard.press(KEY_LEFT_SHIFT); //shift
Keyboard.press('4'); // 4
delay(100);
Keyboard.press(32); // space
delay(500);
}
// 3key : 전체화면
if (digitalRead(A2)) Keyboard.releaseAll();
else{
Keyboard.press(KEY_LEFT_CTRL); //Ctl
Keyboard.press(KEY_LEFT_GUI); //⌘
Keyboard.press('f'); // f
delay(500);
}
digitalWrite(7, HIGH);
digitalWrite(8, LOW);
// 6 key : 부분화면 캡쳐
if (digitalRead(A1)) Keyboard.releaseAll();
else {
Keyboard.press(KEY_LEFT_GUI); //⌘
Keyboard.press(KEY_LEFT_SHIFT); //shift
Keyboard.press('4'); // 4
delay(500);
}
// 2key : Dock 숨기기/표시하기
if (digitalRead(A2)) Keyboard.releaseAll();
else{
Keyboard.press(KEY_LEFT_GUI); //⌘
Keyboard.press(KEY_LEFT_ALT); // Option
Keyboard.press('d'); // d
delay(500);
}
digitalWrite(8, HIGH);
digitalWrite(9, LOW);
// 5 key : 전체화면 캡쳐
if (digitalRead(A1)){
Keyboard.releaseAll();
}
else{
Keyboard.press(KEY_LEFT_GUI); //⌘
Keyboard.press(KEY_LEFT_SHIFT); //Shift
Keyboard.press('3'); // space
delay(500);
}
// 1 Key :emoji macro
if (digitalRead(A2)){
Keyboard.releaseAll();
}
else {
Keyboard.press(KEY_LEFT_CTRL); //control
Keyboard.press(KEY_LEFT_GUI); //⌘
Keyboard.press(32); // space
delay(500);
}
digitalWrite(9, HIGH);
}
void updateEncoder(){
currentStateCLK = digitalRead(CLK);
if (currentStateCLK != lastStateCLK && currentStateCLK == 1){
if (digitalRead(DT) != currentStateCLK) {
delay(10);
Keyboard.pressRaw(Keyboard_Volume_Up_RAW);
Keyboard.releaseRaw(Keyboard_Volume_Up_RAW);
}
else {
delay(10);
Keyboard.pressRaw(Keyboard_Volume_Down_RAW);
Keyboard.releaseRaw(Keyboard_Volume_Down_RAW);
}
}
lastStateCLK = currentStateCLK;
}


완성되었습니다.
이전 볼륨컨트롤러와 1Key 키보드 프로젝트를 통합하여, 9Key 매크로 키보드를 만들어 보았는데요.
현재 상태에서 무한 복붙으로 키를 늘려가면 N키 키보드 제작 가능합니다. 하지만 아두이노 마이크로(Atmega32U4) I/O핀의 한계로 어느정도 넘어가면 Shift Register, 멀티플렉서를 사용해야만 합니다.
시프트레지스터 , 멀티플렉서를 사용하게 되면 코딩의 형태는 지금짠것 크게 달리질 수 있습니다.
긴글 읽어 주셔서 감사드리며, 다음번엔 더 유익한 프로젝트로 돌아오겠습니다.
'키보드 DIY 프로젝트' 카테고리의 다른 글
| 블루투스 42KEY 키보드 (with ESP-WROOM-32 Keyboard, 3D프린팅) (0) | 2025.10.20 |
|---|---|
| (#5) 무선키보드 프로젝트 블루투스 키입력 테스트 (ESP-Bluetooth-Keyboard Library) (0) | 2025.05.07 |
| (#2) 3D프린터로 볼륨컨트롤러 DIY (3D프린터,아두이노) (0) | 2024.10.02 |
| (#1) (자작) 기계식키보드만들기 - 1Key 부터 빌드업 (with PCB, 3D Printing, Arduino, Atmega32u4) (4) | 2024.09.10 |