091

[C/C++] ESP32와 Potentiometer를 이용하여 모드 설정 후 변경하기 본문

Programming Language/C&C++

[C/C++] ESP32와 Potentiometer를 이용하여 모드 설정 후 변경하기

공구일 2025. 3. 15. 16:34
728x90

01. UART(Universal Asynchronous Receiver-Transmitter)

 

- UART : 바동기 직렬 통신 방식으로, 두 장치 간 데이터를 TX(송신)과 RX(수신) 라인을 통해 전송하는 방식(프로토콜)

* 펄스(Pulse) : 짧은 시간 동안 발생하는 전압 또는 전류의 순간적인 변화

* 클럭 신호(Clock Signal) : 일정한 주기로 HIGH와 LOW가 반복되는 신호로, 동기화된 데이터 전송을 제어하는 역할

 

- ESP32에 있는 UART 포트

UART 포트 TX 핀 RX 핀 주요 용도
UART0 GPIO1 GPIO3 기본 Serial(디버깅용)
UART1 GPIO10 GPIO9 추가 시리얼 통신
UART2 GPIO17 GPIO16 보통 센서/모듈 연결

- 이전 글에서 사용했던 Serial 클래스의 메소드들은 바로 이 UART0과 관련된 메소드였던 것으로, ESP32에서는 기본적으로 UART0이 시리얼 통신을 위한 기본 포트로 사용됨 (ex) Serial.begin(), Serial.print()/Serial.println()

 

- 참고로 아래 UART1,2를 사용할 때는 각각 Serial1,Serial2 클래스를 사용해야함

 

Q1. ESP32에서 정해진 GPIO핀이 있는데 LED 통신할 때 왜 GPIO4를 이용한 것인가요? 그래도 됐던 이유가 뭔가요?
A1. 개념이 상충되어 일어나는 오해인데, UART0을 위해 이용되는 GPIO1(송신)과 GPIO3(수신)의 경우, Serial.begin()코드를 통해 이미 내부에서 사용되고 있었으며, 직접 사용한 GPIO4의 경우 LED를 밝기 조절을 위한 PWM 출력 핀임 !

 

02. 입력값을 통해 모드를 설정하여 여러 기능 구현하기 : LED의 밝기(ON/OFF or SMode or PMode)

 

* 하드웨어의 경우, 저번 글( 2025.03.07 - [Programming Language/C&C++] - [C/C++] ESP32와 Potentiometer를 이용하여 LED의 밝기 조절하기 )과 완전히 동일하게 진행하였기 때문에 이 글에서는 추가적인 설명을 하지 않음.

 

https://app.diagrams.net에서 만든 다이어그램(알고리즘 순서도)

- 처음에는 Mode 변경을 좀 더 편하게 하기 위해서 포텐션미터의 변화값에 집중하려고 했었으나, 각 모드끼리 입력받은 값의 방식이 포텐션미터는 ADC이고 ON/OFF를 이용한 조절은 디지털 신호이고 입력값을 통한 조절은 PWM로 달라서 충돌이 발생하기 때문에 입력 값을 통해 각자 이용하는 모드로 구획을 시켜놔야 오류가 발생하지 않음을 발견함

 

- 코드

#define POTENTIOMETER_PIN 34 
#define LED_PIN 4 

int pwmValue = 0; 
bool manualMode = false; //PMode일 때를 falsefh

void setup() {
    Serial.begin(115200);
    pinMode(LED_PIN, OUTPUT);
    Serial.println("Enter 'On' or 'OFF' to control the LED");
    Serial.println("Enter 'PMode' to change the Potentiometer mode");
    Serial.println("Enter 'SMode' to change the Serial mode");
}

void loop() {
  if(Serial.available()){
    String command = Serial.readStringUntil('\n');
    command.trim();
	//ON/OFF
    if(command == "ON"){ 
      digitalWrite(LED_PIN, HIGH);
      Serial.println("LED is ON");
    } else if(command == "OFF"){
      digitalWrite(LED_PIN, LOW);
      Serial.println("LED is OFF");
    } else if (command == "PMode") {
      manualMode = false;
    } else if (command == "SMode") {
      manualMode = true;
    }

    if(manualMode){ //SMode
      if(command == "1"){
        pwmValue = 51;
        analogWrite(LED_PIN, pwmValue);
      } else if (command == "2"){
        pwmValue = 102;
        analogWrite(LED_PIN, pwmValue);
      } else if (command == "3"){
        pwmValue = 153;
        analogWrite(LED_PIN, pwmValue);
      } else if (command == "4"){
        pwmValue = 204;
        analogWrite(LED_PIN, pwmValue);
      } else if (command == "5"){
        pwmValue = 255;
        analogWrite(LED_PIN, pwmValue);
      }
    }
  } 
  
  if(!manualMode) { //PMode
      int potValue = analogRead(POTENTIOMETER_PIN);
      pwmValue = map(potValue, 0, 4095, 0, 255); 
      float volValue = (potValue / 4095.0) * 3.3;  
      analogWrite(LED_PIN, pwmValue); 
      Serial.print("Variable resistor value: ");
      Serial.print(potValue);
      Serial.print(" -> PWM OUT: ");
      Serial.println(pwmValue);
      Serial.print(" -> Voltage: ");
      Serial.println(volValue);
      delay(100);
  }
}

- Serial.available() : 시리얼 버퍼에 수신된 데이터(바이트)가 있는지 확인하는 메소드로, 데이터가 있으면 양수를 없으면 0을 반환함, 그래서 if(Serial.available())은 입력값이 있을 때만 실행되는 조건임

 

- String command = Serial.readStringUntil('\n'); command.trim(); : 시리얼 입력을 한 줄 단위로 읽고, 불필요한 공백을 제거하는 역할을 함

Serial.readStringUntil('\n') : 시리얼 버퍼에서 데이터를 읽어 문자열(String)으로 반환

command.trim() : 문자열의 앞뒤 공백 및 개행문자를 제거함

728x90