본문 바로가기
그림 기능과 기술

자작 아두이노 컨트롤러 회로도와 코드

by ㅁ륜ㅁ 2021. 1. 3.

아래 내용은 아두이노 코딩과 관련된 정보라서 해당 분야에 지식이 있는 사람에게만 읽을 것을 권장한다.

 

코딩처럼 복잡한 소리 말고 컨트롤러 자체에 대한 설명을 보고 싶다면 이 글에 다 나와있다.

 

 

아두이노 컨트롤러의 회로도는 다음과 같다.

 

전체적인 개발은 ESP32 계열 보드인 LOLIN D32 PRO 2.0.0 기판을 이용하였고다.

좌측의 7핀으로 12버튼 키패드를 구현하고,

우편의 6핀으로 단일기능을 시행하는 버튼을 구현한 뒤

건전지 수명을 아끼기 위해 딥슬립 상태에서도 작동하는 12번핀에 버튼을 달아 끄고 켤 수 있게 만들었다.

 

LOLIN D32 PRO 2.0.0는 배터리 커넥터가 달린 상태로 와서 건전지를 연결하기가 수월하나,

보드에 자체적인 회로보호 기능이 없어서 과충전 및 과방전으로 인하여 회로 전체가 고장날 우려가 있다.

이를 방지하기 위해 충전/보호모듈인 TP4056을 추가적으로 달았고,

해당 모듈에서는 곧바로 LOLIN D32 PRO 2.0.0 기판에 달린 배터리 연결부위에 전력을 공급하여 기기가 작동한다.

건전지는 8BitDo Lite에 있는 리튬이온 건전지를 사용하였다.

 

 

아래는 최종 컨트롤러에 이용된 코드 전문이며 중간중간에 한글어로 해설을 달아두었다.

 

인터넷을 검색하여 찾을 수 있는 각종 코드를 짬뽕하여 만들었기에 매우 비효율적일 것으로 짐작한다.

 

github.com/T-vK/ESP32-BLE-Keyboard - BLE 키보드 라이브러리. IOS 환경에서 작동할 수 있다.

www.circuitbasics.com/how-to-set-up-a-keypad-on-an-arduino/ - 매트릭스 키패드 라이브러리. 12버튼 키패드를 코딩하는데 참조하였다.

 

더보기

 

#include <MixKeypad.h> //컨트롤러를 위해 만든 커스텀 라이브러리 불러오기

 

BleKeyboard bleKeyboard; //단일버튼 기능을 정의하기 위한 키보드 정보 불러오기

 

//3x4 매트릭스 키보드 행렬 정의하기

const byte ROWS = 3; //3행

const byte COLS = 4; //4열

//키패드에 있는 버튼 이름 정의하기

char hexaKeys[ROWS][COLS] = {

{'0','1','2','3'},

{'4','5','6','7'},

{'8','9','A','B'}

};

byte rowPins[ROWS] = {14, 27, 26}; //행 역할을 할 핀 지정하기

byte colPins[COLS] = {25, 33, 32, 13}; //열 역할을 할 핀 지정하기

 

//위 정보를 바탕으로 커스텀 키패드 구현하기

Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

 

//opt, shift, cmd 기능을 실행할 단일버튼 핀 지정하기

const int PIN15 = 15;

const int PIN02 = 02;

const int PIN00 = 00;

 

//그 외 기능 하나만을 실행할 단일버튼 핀 지정하기

const int PIN04 = 04;

const int PIN05 = 05;

const int PIN18 = 18;

const int PIN12 = 12;

 

//해당 변수는 꾸욱 눌리는 걸 프로그램하기 위해 계속 변화합니다:

int buttonPushCounterSHIFT = 0; // 현재까지 shift 버튼이 눌린 횟수

int buttonStateSHIFT = 0; // shift 버튼의 현재 상태

int lastButtonStateSHIFT = 0; // shift 버튼의 이전 상태

 

int buttonPushCounterCMD = 0; // 현재까지 cmd 버튼이 눌린 횟수

int buttonStateCMD = 0; // cmd버튼의 현재 상태

int lastButtonStateCMD = 0; // cmd 버튼의 이전 상태

 

int buttonPushCounterOPT = 0; // 현재까지 opt 버튼이 눌린 횟수

int buttonStateOPT = 0; // opt 버튼의 현재 상태

int lastButtonStateOPT = 0; // opt 버튼의 이전 상태

 

//기기가 켜졌을 때 이유

void print_wakeup_reason(){

esp_sleep_wakeup_cause_t wakeup_reason;

 

wakeup_reason = esp_sleep_get_wakeup_cause();

 

switch(wakeup_reason)

{

case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;

case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;

case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;

case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;

case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;

default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;

}

}

 

//기기가 딥 슬립 모드에 있을 때 12번 핀이 눌리는 걸 인식하는 코드

void IRAM_ATTR isr(){

while(digitalRead(PIN12) == LOW ){

//Do nothing

}

detachInterrupt(digitalPinToInterrupt(12)); //because later used for wake up

Serial.println("Going to sleep now");

esp_sleep_enable_ext0_wakeup(GPIO_NUM_12,0); //1 = High, 0 = Low connected to GPIO12

esp_deep_sleep_start();

}

 

 

void setup() {

 

//실제로 12번 핀을 누르면 켜지게 만드는 코드

esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);

// disable all wakeup sorces:

pinMode (PIN12, INPUT_PULLUP); //pin 34-39 do not offer internal resistors; This will only work if RTC peripherals

//are on in sleep, otherwise use 10kOhm external resistor for pull down

 

//기기가 켜졌을 때 정보

Serial.begin(115200);

delay(1000);

Serial.println("Wake up!");

//Print the wakeup reason for ESP32

print_wakeup_reason();

attachInterrupt(digitalPinToInterrupt(12), isr, FALLING);

 

Serial.println("Starting BLE work!");

bleKeyboard.begin();

pinMode (PIN15, INPUT_PULLUP);

pinMode (PIN02, INPUT_PULLUP);

pinMode (PIN00, INPUT_PULLUP);

pinMode (PIN04, INPUT_PULLUP);

pinMode (PIN05, INPUT_PULLUP);

pinMode (PIN18, INPUT_PULLUP);

 

 

boolean running = true;

 

}

 

void loop(){

 

 

if(bleKeyboard.isConnected()) {

 

//12버튼 매트릭스 키패드. 각 버튼에 필요한 키보드 키를 지정한다.

{

char customKey = customKeypad.getKey();

 

if (customKey){

switch(customKey){

case '2':

Serial.println("Sending 'j'");

bleKeyboard.write('j');

delay(50);

break;

case '3':

Serial.println("Sending 'y'");

bleKeyboard.write('y');

delay(100);

break;

case '6':

Serial.println("Sending 'z'");

bleKeyboard.write('z');

delay(50);

break;

case '7':

Serial.println("Sending 'd'");

bleKeyboard.write('d');

delay(50);

break;

case '1':

Serial.println("Sending 'b'");

bleKeyboard.write('b');

delay(50);

break;

case '5':

Serial.println("Sending 'e'");

bleKeyboard.write('e');

delay(50);

break;

case '0':

Serial.println("Sending 'p'");

bleKeyboard.write('p');

delay(50);

break;

case '4':

Serial.println("Sending 'g'");

bleKeyboard.write('g');

delay(50);

break;

case '9':

Serial.println("Sending 'm'");

bleKeyboard.write('m');

delay(50);

break;

case 'B':

Serial.println("Sending 'i'");

bleKeyboard.write('i');

delay(50);

break;

case '8':

Serial.println("Sending 'w'");

bleKeyboard.write('w');

delay(50);

break;

case 'A':

Serial.println("Sending 'r'");

bleKeyboard.write('r');

delay(50);

break;

}

}

}

 

//opt, shift, cmd키 코딩. 해당 버튼은 꾹 눌리는 걸 구현하기 위해 특별한 코드가 작성된다.

buttonStateSHIFT = digitalRead(PIN02);

if (buttonStateSHIFT != lastButtonStateSHIFT) {

if (buttonStateSHIFT == LOW ){

buttonPushCounterSHIFT++;

Serial.println("Pressing 'LeftShift'");

bleKeyboard.press(KEY_LEFT_SHIFT);

Serial.print("number of button pushes: ");

Serial.println(buttonPushCounterSHIFT);

} else{

Serial.println("releaseing 'LEFTSHIFT'");

bleKeyboard.release(KEY_LEFT_SHIFT);

}

delay(50);

}

 

lastButtonStateSHIFT = buttonStateSHIFT;

 

 

buttonStateCMD = digitalRead(PIN15);

if (buttonStateCMD != lastButtonStateCMD) {

if (buttonStateCMD == LOW ){

buttonPushCounterCMD++;

Serial.println("Pressing 'LeftCMD'");

bleKeyboard.press(KEY_LEFT_GUI);

Serial.print("number of button pushes: ");

Serial.println(buttonPushCounterCMD);

} else{

Serial.println("releaseing 'LEFTCMD'");

bleKeyboard.release(KEY_LEFT_GUI);

}

delay(50);

}

 

lastButtonStateCMD = buttonStateCMD;

 

 

buttonStateOPT = digitalRead(PIN00);

if (buttonStateOPT != lastButtonStateOPT) {

if (buttonStateOPT == LOW ){

buttonPushCounterOPT++;

Serial.println("Pressing 'OPT'");

bleKeyboard.press(KEY_LEFT_ALT);

Serial.print("number of button pushes: ");

Serial.println(buttonPushCounterOPT);

} else{

Serial.println("releaseing 'OPT'");

bleKeyboard.release(KEY_LEFT_ALT);

}

delay(50);

}

 

lastButtonStateOPT = buttonStateOPT;

 

 

//그 외 기타 키 지정. [, ]와 같이 브러시 크기를 조절하는 키보드 키와 cmd+s로 저장을 간단하게 할 수 있게 한다.

if(digitalRead(PIN04) == LOW ){

Serial.println("Sending '['");

bleKeyboard.write('[');

delay(200);

}

 

if(digitalRead(PIN05) == LOW ){

Serial.println("Sending ']'");

bleKeyboard.write(']');

delay(200);

}

 

if(digitalRead(PIN18) == LOW ){

Serial.println("Sending 'Cmd+S'");

bleKeyboard.press(KEY_LEFT_GUI);

bleKeyboard.write('s');

delay(100);

bleKeyboard.release(KEY_LEFT_GUI);

delay(200);

}

 

 

}

 

}

deepsleeponebutton.ino
0.01MB

해당 아두이노 코드. 다운로드해서 아래 라이브러리와 함께 곧바로 사용하면 된다.

MixKeypad.h
0.01MB

매트릭스 키보드를 만들기 위한 라이브러리와 BLE 키보드 라이브러리 두 개를 합쳐서 만든 자작 라이브러리.

쓸데없이 라이브러리 2 개를 따로따로 불러오게 하는 대신에 필요한 기능만 빼내서 만들었다.

댓글