- ESP8266/ESP32 GPIO Port
- ESP8266 GPIO Port
- ESP32 GPIO Port
- Arduino에서 자주 사용하는 GPIO 관련 함수
- ESP32 개발보드에 내장된 Switch(Push button)와 LED
- 프로그램 예: Switch(Push button)와 LED
- 외부 인터럽트(External interrupt)
- ESP8266/ESP32 GPIO Port와 Interrupt 관련 페이지 보기
- ESP8266 GPIO Port
- NodeMCU-8266의 Pin 예: 개발보드에 따라 Pin 배열이 다를 수 있기 때문에 자신이 사용하는 보드의 Pin 배열을 확인하여야 한다.
- ESP8266 12-E chip에는 17개의 다 기능 핀이 있다. 그러나 모든 Pin이 개발보드의 Pin에 연결되어 있는 것은 아니다.
- 위 NodeMCU-8266 개발보드(ESP8266 개발보드는 ESP-12E 기반 개발 보드 임)는 13개의 Pin을 갖고 있다. 개발보드에 따라 다른 Pin 배열을 갖고 있을 수 있기 때문에 자신 사용하는 개발보드의 Pin 배열을 확인하고 사용하여야 한다.
- GPIO6 - GPIO11은 통합된 SPI flash에 연결되어 있기 때문에 다른 용도로는 권장되지 않는다. NodeMCU-8266 개발보드의 Pin에는 이들 Pin이 연결되어 있지 않다.
- 아래 Pin은 Booting 시 영향을 받는다. Booting 시 영향을 고려하여 Pin을 사용하여야 한다.
- GPIO0: 만약 LOW로 Pulled 상태이면 Booting에 실패하게 된다.
- GPIO1: BOOT 시 HIGH 상태, 만약 LOW로 Pulled 상태이면 Booting에 실패하게 된다.
- GPIO2: BOOT 시 HIGH 상태, 만약 LOW로 Pulled 상태이면 Booting에 실패하게 된다.
- GPIO3: BOOT 시 HIGH 상태가 된다.
- GPIO9: BOOT 시 HIGH 상태가 된다.
- GPIO10: BOOT 시 HIGH 상태가 된다.
- GPIO15: 만약 HIGH로 Pulled 상태이면 Booting에 실패하게 된다.
- GPIO16: BOOT 시 HIGH 상태가 된다.
- GPIO0는 개발보드의 Switch에 연결되어 있고 Booting 시 LOW 이면 FLASH Mode, HIGH 이면 BOOT Mode 가 된다. Booting이 종료된 다음에는 다른 용도로 사용할 수 있다.
- GPIO2는 개발보드의 LED에 연결되어 있다. LED와 함께 연동되는 것이 문제되지 않는 경우에는 다른 용도로 사용할 수 있다.
- GPIO16을 사용하여 ESP8266을 Deep sleep에서 Wake up 할 수 있다. Deep sleep에서 Wake up 용도로 사용하려면 GPIO16을 RST 핀에 연결해야 한다.
- ESP32 GPIO Port
- NodeMCU-32의 Pin 예: 개발보드에 따라 Pin 배열이 다를 수 있기 때문에 자신이 사용하는 보드의 Pin 배열을 확인하여야 한다.
- ESP32 chip에는 48개의 다 기능 핀이 있다. 그러나 모든 Pin이 개발보드의 Pin에 연결되어 있는 것은 아니다.
- 위 NodeMCU-32 개발보드(ESP32 개발보드는 ESP32-WROOM-32E Module 기반 개발보드 임)는 38개의 Pin을 갖고 있다. ESP32 DEVKIT V1 DOIT 개발보드는 36 Pin을 갖고 있기 때문에 자신이 사용하는 개발보드의 Pin 배열을 확인하고 사용하여야 한다.
- 입력 전용 Pin: GPIO34, 35,36,39는 입력 전용 Pin 이다. 또한 이들 Pin은 내부 pull-down 저항이 없다.
- GPIO6 - GPIO11은 ESP-WROOM-32에 통합된 SPI flash에 연결되어 있기 때문에 다른 용도로는 권장되지 않는다. 따라서 프로젝트에서 이들 핀을 사용하지 않아야 한다.
- GPIO1,3,5,6 - 11(ESP-WROOM-32에 통합된 SPI flash에 연결됨), 14, 15는 부팅 또는 Reset 시 HIGH 상태이거나 PWM 신호를 출력(Boot mode selection 자료를 참고요)한다. 이러한 GPIO에 연결된 장치가 있는 경우 ESP32가 Reset 되거나 부팅될 때 예기치 않은 결과가 발생할 수 있다.
- 각각의 GPIO의 최대 전류는 40mA 이다. LED 하나는 약 10 - 15mA의 전류를 필요로 한다.
- GPIO0는 개발보드의 Switch에 연결되어 있고 Booting 시 LOW 이면 FLASH Mode, HIGH 이면 BOOT Mode 가 된다. Booting이 종료된 다음에는 다른 용도로 사용할 수 있다.
- GPIO2는 개발보드의 LED에 연결되어 있다. LED와 함께 연동되는 것이 문제되지 않는 경우에는 다른 용도로 사용할 수 있다.
- Arduino에서 자주 사용하는 GPIO 관련 함수
- pinMode(pin, mode): GPIO Pin의 Mode를 설정한다.
- pin: GPIO Pin 번호
- mode: Pin mode
- INPUT: 해당 Pin을 Input port로 설정(High impedance 상태)한다.
- INPUT_PULLUP: 해당 Pin을 Input port로 설정하고, Pull Up 저항을 Enable 한다.
- INPUT_PULLDOWN: 해당 Pin을 Input port로 설정하고, Pull Down 저항을 Enable 한다.
- OUTPUT: 해당 Pin을 Output port로 설정한다.
- digitalWrite(pin, value)
- value: Pin에 value 값(HIGH or LOW)을 출력한다.
- digitalRead(pin): Pin의 상태(HIGH or LOW) 값을 읽는다.
- Push button SW(GPIO0)와 LED(GPIO2) 실험을 위한 회로 구성 예
주: Pin과 GND 사이에 Switch를 연결한 경우 Switch가 Open 상태일 때 Pin은 High 상태가 되고 Close 상태일 때 Low가 된다.
주: Pin과 VDD 사이에 Switch를 연결한 경우 Switch가 Open 상태일 때 Pin은 Low 상태가 되고 Close 상태일 때 High가 된다.
위 회로의 SW(GPIO0)와 LED(GPIO2)는 아래와 같이 ESP32 개발보드에 내장되어 있기 때문에 실제 회로 구성은 하지 않아도 된다.
ESP32 개발보드에 내장된 SW(GPIO0)와 LED(GPIO2) 위치
Switch의 상태를 LED에 출력하는 프로그램 예: sw_status_led.ino
// Pin 번호를 설정한다.
// ESP 개발 보드에 내장된 Button SW(GPIO0)를 사용한다.
const int buttonPin = 0;
// ESP 개발 보드에 내장된 LED(GPIO2)를 사용한다.
const int ledPin = 2;
// Button 상태를 저장하는 Variable
int buttonState = 0;
void setup() {
// Pushbutton pin을 Input pin으로 설정한다.
pinMode(buttonPin, INPUT_PULLUP);
// LED pin을 Output pin으로 설정한다.
pinMode(ledPin, OUTPUT);
}
void loop() {
// Pushbutton의 상태를 읽는다.
buttonState = digitalRead(buttonPin);
// if Pushbutton 이 pressed 되었으면
if (buttonState == HIGH) {
// LED를 on 한다.
digitalWrite(ledPin, HIGH);
} else {
// LED를 off 한다.
digitalWrite(ledPin, LOW);
}
}
- LED: 개발보드에 내장(GPIO2)되어 있기 때문에 별도의 회로를 필요로 하지 않는다.
- Button switch: 개발보드에 내장(GPIO0)되어 있기 때문에 별도의 회로를 필요로 하지 않는다.
- Arduino IDE를 실행하고Arduino IDE의 사용 환경(실행에 사용할 보드와 COM Port 선택)이 바르게 설정되어 있는지 확인한다.
- 위 프로그램을 복사하여 Arduino IDE의 편집 창에 복사한다.
- 편집 창의 프로그램을 File name "sw_status_led.ino"로 저장 한다.
- 실험
- "업로드" Icon을 클릭하면 프로그램이 컴파일되고 개발보드로 전송이 시작되는 매세지(Connecting... )가 출력된다.
- "Connecting... " 메세지가 출력된 다음 약 2Sec 동안 개발보드의 GPIO0 SW를 누르고 있으면(NodeMCU ESP8266 개발보드는 GPIO0를 프로그램에서 제어하기 때문에 GPIO0 SW를 누르지 않아도 됨) 개발 보드에 업로드가 시작된다.
- 업로드가 종료되면 프로그램이 자동으로 실행된다.
- 개발보드의 BOOT 버튼(GPIO0 Pin을 사용함)을 누르면 ESP32 보드인 경우 LED(GPIO2)가 On 되고 누르지 않으면 Off 상태가 된다. ESP8266 보드는 누르면 LED(GPIO2)가 Off 되고 누르지 않으면 On 상태가 된다.
참고자료: "Arduino IDE에 ESP8266/32 Board Manager 설치하기"
참고자료: "ESP8266/32에 Code Uploading 하기"
- External interrupt 개요
- External interrupt 은
- External interrupt는 주변장치의 서비스 요청에 맞추어(동기 하여) 서비스를 실행 한다.
- 외부 장치의 요구에 의해서 Interrupt가 발생하면 현재 실행 중인 프로그램을 잠시 멈추고, Interrupt에 의하여 요구된 작업을 먼저 수행한 후에 다시 원래의 프로그램으로 복귀하여 실행 한다.
- Embedded System의 Program은 대부분 Interrupt Drive 방식으로 작성 한다.
- External Interrupt에 사용하는 GPIO Pins
- ESP32의 GPIO Pin은 모두 외부 신호를 받아 이 신호에 대응하는 인터럽트(External interrupt)를 발생 시키는 목적으로 사용 할 수 있다.
- ESP8266의 경우 GPIO16을 제외한 모든 GPIO 핀을 사용하여 외부 인터럽트를 생성할 수 있다.
- External Interrupt Trigger Events
- RISING : Rising Edge에서 Interrupt이 Trigger 된다.
- FALLING : FALLING Edge에서 Interrupt이 Trigger 된다.
- HIGH : HIGH 상태에서 Interrupt이 Trigger 된다.
- LOW : LOW 상태에서 Interrupt이 Trigger 된다.
- CHANGE : Pin의 상태가 변하면(HIGH -> LOW or LOW -> HIGH) Interrupt이 Trigger 된다.
- External Interrupt 설정에 사용하는 함수
- Arduino Core에서는 아래와 같은 함수를 이용하여 인터럽트 기능을 활성화 한다.
- GPIO_pin: External Interrupt Trigger에 사용하는 Pin 번호
- ISR: Interrupt Service Routine 이름
- Event: Trigger Event Type
- Arduino Core에서는 아래와 같은 함수를 이용하여 인터럽트 기능을 비 활성화 한다.
- GPIO_pin: External Interrupt Trigger에 사용하는 Pin 번호
- IRAM_ATTR 식별자(Identifier)
- 아래 함수는 noInterrupts()에 의해 비활성화된 인터럽트를 다시 활성화 한다.
- 아래 함수는 Interrupts를 비 활성화 한다.
- 프로그램 실행 중 Interrupts를 Turn on(interrupts()) 또는 Turn off(noInterrupts()) 하는 예
각 외부 인터럽트 핀에 대해 인터럽트를 트리거하는 5가지 다른 이벤트(응용 프로그램에 따라 선택)가 있다.
펄스 신호의 4가지 상태 예: 4가지 상태에 CHANGE를 포함하면 5가지 상태가 된다.
attachInterrupt(GPIO_pin, ISR, Event);
detachInterrupt(GPIO_pin);
ISR을 내부 RAM memory에 배치하기 위하여 Espressif에서 권장하는 식별자(Identifier)이다. ISR을 내부 RAM memory에 배치하면 Flash memory에 배치된 경우에 비교하여 매우 빠르게 컨텍스트 전환 및 서비스가 실행된다.
interrupts();
noInterrupts();
주: External interrupt 이해에 도움이 되는 참고자료: "ATMega128 External Interrupt"
// 여기에 Interrupt Function(ISR)를 작성한다.
// Power-On 또는 ResetSetup 시 첫번째로 한번만 실행되는 설정(Setup) 프로그램을 작성한다.
void setup()
{
}
// Startup function이 실행된 후 반복(Loop)되는 프로그램을 작성한다.
void loop()
{
noInterrupts();
// 시간에 민감한(실행 중 Interrupt 가 발생하면 안되는 Code)가 이 곳에 위치 한다.
interrupts();
// 시간에 민감하지 않은(실행 중 Interrupt 가 발생하여도 되는 Code)가 이 곳에 위치 한다.
}
- Switch를 누르면 LED의 상태가 Toggle(현재 상태가 On 이면 Off 상태로, Off 상태인 경우는 On 상태로 됨)되는 프로그램 예
// ESP 개발 보드에 내장된 Button SW(GPIO0)를 사용한다.
const int buttonPin = 0;
// ESP 개발 보드에 내장된 LED(GPIO2)를 사용한다.
const int ledPin = 2;
// 외부 인터럽트가 발생하면 실행되는 ISR(interrupt service routine)
void IRAM_ATTR Ext_INT_ISR()
{
// Toggle The LED
digitalWrite(ledPin, !digitalRead(ledPin));
}
// GPIO 입출력 핀 과 AttachInterrupt를 초기화한다.
void setup()
{
// Pushbutton pin을 Input pin으로 설정한다.
pinMode(buttonPin, INPUT_PULLUP);
// LED pin을 Output pin으로 설정한다.
pinMode(ledPin, OUTPUT);
// Button SW가 눌리는 순간(Falling edge)
// 인터럽트 ISR(Ext_INT_ISR)가 실행되도록 설정한다.
attachInterrupt(buttonPin, Ext_INT_ISR, FALLING);
}
// 무한 Loop를 실행하며 외부 인터럽트가 발생하기를 기다린다.
void loop()
{
// Do Nothing...
}
- LED: 개발보드에 내장(GPIO2)되어 있기 때문에 별도의 회로를 필요로 하지 않는다.
- Button switch: 개발보드에 내장(GPIO0)되어 있기 때문에 별도의 회로를 필요로 하지 않는다.
- Arduino IDE를 실행하고Arduino IDE의 사용 환경(실행에 사용할 보드와 COM Port 선택)이 바르게 설정되어 있는지 확인한다.
- 위 프로그램을 복사하여 Arduino IDE의 편집 창에 복사한다.
- 편집 창의 프로그램을 File name "switch_toggle_led_interrupt.ino"로 저장 한다.
- 실험
- "업로드" Icon을 클릭하면 프로그램이 컴파일되고 개발보드로 전송이 시작되는 매세지(Connecting... )가 출력된다.
- "Connecting... " 메세지가 출력된 다음 약 2Sec 동안 개발보드의 GPIO0 SW를 누르고 있으면(NodeMCU ESP8266 개발보드는 GPIO0를 프로그램에서 제어하기 때문에 GPIO0 SW를 누르지 않아도 됨) 개발 보드에 업로드가 시작된다.
- 업로드가 종료되면 프로그램이 자동으로 실행된다.
- 개발보드의 BOOT 버튼(GPIO0 Pin을 사용함)을 누르면 ESP32 보드인 경우 LED(GPIO2)의 상태가 Toggle(현재 Off 인 경우는 On 상태로 되고, 현재 On 인 경우는 Off 상태로) 된다.
주: Switch의 상태가 이상적이지 않기 때문에 Switch를 누르면 Switch bouncing 현상에 의하여 가끔 오동작이 발생한다.