카테고리 없음

(esp32 로봇 카) 블루투스로 기본 동작

미친토끼 2025. 6. 2. 08:30

 

RC카의 기본 동작을 블루투스로 지시하는 흔한 코드다. 아두이노 우노와는 달리 블루투스를 기본 내장하고 있기 때문에 별도 설치할 필요가 없다. Serial Bluetooth Terminal 이라는 안드로이드용 앱을 사용하고 있는데, 화면을 옆으로 돌리면 M0~M9까지 모두 10개 버턴을 사용할 수 있다. 여기에 0~9를 맵핑시키고, 이 버턴을 누를 경우 각각, 

0: 전진, 1: 좌회전(앞쪽으로), 2: 좌회전(뒤쪽으로), 3: 가속, 4: 정지, 5: 정지, 6: 감속, 7: 우회전(뒤쪽), 8: 우회전(앞쪽), 9: 후진

을 실행하도록 switch 문을 이용했다. 이렇게 하니까 단점이 버턴을 누를 때에만 switch 문이 실행되어, 동작 중에는 속도 조절이 되지 않는 단점이 있었다. switch 문 밖에서 동작을 하도록 수정해야겠다. 일단 기본 코드... (여기서 조금씩 기능을 붙여 나갈 생각이다.)

// for esp32 

#include "BluetoothSerial.h"

BluetoothSerial SerialBT;
String device_name = "ESP32-main";

//values for motors
// Motor A
int ENA = 14;
int IN1 = 27;
int IN2 = 26;
// Motor B
int ENB = 25;
int IN3 = 33;
int IN4 = 32;

int speed = 140; // default speed
int myDelay = 100;

void setup() {
  Serial.begin(115200);
  SerialBT.begin(device_name);
  Serial.printf("The device with name '%s' is started.\nNow you can pair it with Bluetooth!\n", device_name.c_str());
  
  // init motors
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);

  pinMode(ENB, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
}

void forward(int speed1_, int speed2_) {
  analogWrite(ENA, speed1_);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  analogWrite(ENB, speed2_);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void backward(int speed1_, int speed2_) {
  analogWrite(ENA, speed1_);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  analogWrite(ENB, speed2_);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

void left_forward(int speed_) {
  analogWrite(ENB, speed_); 
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void right_forward(int speed_) {
  analogWrite(ENA, speed_);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW); 
}

void left_backward(int speed_) {
  analogWrite(ENB, speed_);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW); 
}

void right_backward(int speed_) {
  analogWrite(ENA, speed_);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW); 
}

void stop() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW); 
}

void loop() {
  if (SerialBT.available()) {
    char c = SerialBT.read();

    switch (c) {
      case '0':  // forward
        SerialBT.println("forward");
        forward(speed, speed);
        break;
      case '1':  // left forward
        SerialBT.println("left forward");
        left_forward(speed);
        break;
      case '2':  // left backward
        SerialBT.println("left backward");
        left_backward(speed);
        break;
      case '3':  // speed up by 10
        SerialBT.println("speed up by 10");
        speed += 10;
        if (speed > 250) speed = 250;
        break;
      case '4':  // stop
        SerialBT.println("stop!");
        stop();
        break;
      case '5':  // stop
        SerialBT.println("stop!");
        stop();
        break;
      case '6':  // speed down by 10
        SerialBT.println("speed down by 10");
        speed -= 10;
        if (speed < 0) speed = 0;
        break;
      case '7':  // right backward
        SerialBT.println("right backward");
        right_backward(speed);
        break;
      case '8':  // right forward
        SerialBT.println("right forward");
        right_forward(speed);
        break;
      case '9':  //backward
        SerialBT.println("backward");
        backward(speed, speed);
        break;
      default:
        ;
    }
  }
}

 

주행 중 실시간 속도 조절이 되지 않는 문제는, 속도 조절과 주행 관리를 별도의 변수로 관리해야 해결할 수 있다. 특히 속도 조절을 한 다음에, 그 바뀐 속도 변수를 가져와서 기존 주행을 이어가도록 해야 한다. 이 부분은 어렵지 않은데, 한 가지 주의할 점은, esp32의 Adafruit 블루투스 라이브러리는 아두이노의 그것과는 달라서 readStringUntil() 함수를 지원하지 않는다는 것이다. 이것 때문에 블루투스 입력에서 들어오는 '\n'이 처리되지 않아서 오동작해서 그것을 처리하느라 시간이 좀 걸렸다. 그래서 readStringUntil() 함수를 만들어 처리하니까 문제가 해결되었다.

// for esp32 rc car

#include "BluetoothSerial.h"

BluetoothSerial SerialBT;
String device_name = "ESP32-main";

//values for motors
// Motor A
const uint8_t ENA = 14;
const uint8_t IN1 = 27;
const uint8_t IN2 = 26;
// Motor B
const uint8_t ENB = 25;
const uint8_t IN3 = 33;
const uint8_t IN4 = 32;

int speed = 140; // default speed

void setup() {
  Serial.begin(115200);
  SerialBT.begin(device_name);
  Serial.printf("The device with name '%s' is started.\nNow you can pair it with Bluetooth!\n", device_name.c_str());
  
  // init motors
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);

  pinMode(ENB, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
}

void forward(int speed1_, int speed2_) {
  analogWrite(ENA, speed1_);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  analogWrite(ENB, speed2_);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void backward(int speed1_, int speed2_) {
  analogWrite(ENA, speed1_);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  analogWrite(ENB, speed2_);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

void left_forward(int speed_) {
  analogWrite(ENB, speed_); 
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void left_backward(int speed_) {
  analogWrite(ENA, speed_);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW); 
}

void right_forward(int speed_) {
  analogWrite(ENA, speed_);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW); 
}

void right_backward(int speed_) {
  analogWrite(ENB, speed_);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW); 
}

void stop() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW); 
}

String BTreadStringUntil(char end_) {
  String result = "";
  char c_;
  while (SerialBT.available()) {
    c_ = SerialBT.read();
    if (c_ != end_) result += String(c_);
  }
  return result;
}

uint8_t running_mode = 4; // default is stop, should be one of {0, 1, 2, 4, 5, 7, 8, 9}, 3 and 6 are speed control
String running_mode_str[10] = {"forward", "left forward", "left backward", "speed up", "stop", "stop", "speed down",
      "right backward", "right forward", "backward"};
uint8_t c = 4;

void loop() {
  if (SerialBT.available()) {
    String message = BTreadStringUntil('\n');
    //Serial.println(message);
    uint8_t c = message.toInt();
    if (c == 3) {
      SerialBT.println(running_mode_str[c]);
      speed += 10;
      if (speed > 250) speed = 250;
    } else if (c == 6) {
      SerialBT.println(running_mode_str[c]);
      speed -= 10;
      if (speed < 0) speed = 0;
    } else {
      running_mode = c;
      //Serial.print("else_running_mode: "); Serial.println(running_mode);      
    }
    //Serial.print("running_mode: "); Serial.println(running_mode);  
    switch (running_mode) {
      case 0:  // forward
        SerialBT.println(running_mode_str[running_mode]);
        forward(speed, speed);
        break;
      case 1:  // left forward
        SerialBT.println(running_mode_str[running_mode]);
        left_forward(speed);
        break;
      case 2:  // left backward
        SerialBT.println(running_mode_str[running_mode]);
        left_backward(speed);
        break;
      case 4:  // stop
      case 5:  // stop
        SerialBT.println(running_mode_str[running_mode]);
        stop();
        break;
      case 7:  // right backward
        SerialBT.println(running_mode_str[running_mode]);
        right_backward(speed);
        break;
      case 8:  // right forward
        SerialBT.println(running_mode_str[running_mode]);
        right_forward(speed);
        break;
      case 9:  //backward
        SerialBT.println(running_mode_str[running_mode]);
        backward(speed, speed);
        break;
      default:
        ;
    }
  }
}