버튼으로 전진, 후진 하기 (with ESP32)

GAON PARK·2023년 11월 23일
0
post-custom-banner

회로 연결

ESP32에 자체 풀업저항이 달려있던가 확신이 없어서 저항까지 연결했었는데, 인터럽트에 대해 알아보면서 자체 저항도 달려있다는 걸 알게 되어 그냥 바로 연결했다.

btnesp32 pin
go1gnd
go2gpio18
back1gnd
back2gpio19

ESP32 코드

원래는 버튼을 누를 때마다 인터럽트를 발생시켜서 mqtt 송신을 하려고 시도해봤지만, 다른 버튼과 인터럽트가 충돌해서 결국 thread로 press/release 상태를 측정했다.

  • go/back 버튼에 맞춘 pin 번호를 각각 define 한다.
  • cmd_button_check() : 커스텀 객체가 아닌, 기본 Thread 객체를 만들어서 interval 마다 주기적으로 실행할 함수를 정의했다.
  • COMMAND_XXX는 값이 바뀌지 않는 한 mqtt 송신을 한 번만 보내도록 하기 위해 만든 bool 변수로 volatile 키워드를 추가해 과하게 똑똑한 컴파일러의 방해(!)를 차단했다.
  • command_all_false() 를 통해 함수 하나를 호출하면서 상태 bool 값을 모두 false로 만들고, 입력된 커맨드에 따라 하나씩 수정하는 식으로 재사용했다.
#define GO_BUTTON 18                    // the number of the go button pin
#define BACK_BUTTON 19                  // the number of the back button pin

// ... EspMQTTClient 코드
// ... mpu6050 값을 읽을 스레드 클래스 관련 코드
// ... mqtt 송신용 tx() 함수
// ... 

// 한 번만 보내기 위한 flg 변수
volatile bool COMMAND_GO = false,
              COMMAND_BACK = false,
              COMMAND_STOP = false,
              COMMAND_LEFT_MIN = false,
              COMMAND_LEFT_MAX = false,
              COMMAND_RIGHT_MIN = false,
              COMMAND_RIGHT_MAX = false,
              COMMAND_MID = false;

void command_all_false(void) {
  COMMAND_GO = false;
  COMMAND_BACK = false;
  COMMAND_STOP = false;
}

// 스레드가 설정된 interval에 맞춰 주기적으로 실행할 함수
void cmd_button_check(void) {
  if (digitalRead(GO_BUTTON) == LOW && !COMMAND_GO) {
    // Serial.println("go");
    tx(CMD_TOPIC, "go");
    command_all_false();
    COMMAND_GO = true;
  } else if (digitalRead(BACK_BUTTON) == LOW && !COMMAND_BACK) {
    // Serial.println("back");
    tx(CMD_TOPIC, "back");
    command_all_false();
    COMMAND_BACK = true;
  } else if (digitalRead(GO_BUTTON) == HIGH && digitalRead(BACK_BUTTON) == HIGH && !COMMAND_STOP) {
    // Serial.println("stop");
    tx(CMD_TOPIC, "stop");
    command_all_false();
    COMMAND_STOP = true;
  }
}
  • thread controller 에 thread 객체 (go, back command 입력 전용) 를 추가한다.
  • loop 에서 controller.run() 을 해주면 등록된 스레드 객체가 모두 start/run 된다.
// create thread
Thread cmd_th = Thread()

// ... thread controller 관련 코드

void setup(void) {
  // ... serial monitor begin
  // ... mqtt client enable 

  // command (go/back) button 
  pinMode(GO_BUTTON, INPUT_PULLUP);
  pinMode(BACK_BUTTON, INPUT_PULLUP);

  // callback thread func
  cmd_th.onRun(cmd_button_check);
  cmd_th.setInterval(50);

  // ... mpu thread add to thread controller
  // cmd thread add to thread controller
  controller.add(&cmd_th);

  // ... mpu init code 
}
post-custom-banner

0개의 댓글