8차시(심화) : AI 탑재 RC카
# 8차시(심화) 목차
AI 오픈소스 와 아두이노
[실습 8] Handpose AI 모델로 RC카 제어하기
실습 8-1. ML5 AI 오픈소스 Handpose 사용해보기
실습 8-2. Handpose AI 모델 시리얼통신 출력 코드 추가
실습 8-3. Handpose AI 모델 시리얼통신 출력 과 아두이노 연결하기
[마무리] 배움 내용 정리하기
AI 오픈소스와 아두이노
인공지능 모델이 현실 세계에서 동작하기 위해서는 인공지능이 판독한 결과를 구현할 수 있는 물리적 환경이 필요하다. 즉, 아두이노처럼 전자 회로를 제어할 수 있는 마이크로프로세서가 인공지능과 연결되어 인공지능의 판독에 따라 전자부품을 제어할 수 있는 시스템이 필요하다. 이번 미션에서는 ML5에서 제공하는 인공지능 모델을 p5.js 환경에서 구현해 보고, 이를 시리얼 통신을 통해 아두이노와 연결하여 RC카 모터를 AI 판독에 따라 제어하는 미션을 수행할 수 있다.
[실습 8 ] Handpose AI 모델로 RC카 제어하기
우리의 목표 : ML5 모델을 이용하여 손 감지 AI 모델을 만들어 보자.
ML5* 사이트에서는 각종 AI 모델을 제공한다. 특히 AI 모델들은 미리 훈련이 완료된 모델들이기 때문에 개발 환경에 맞게 가져와서 쉽게 사용할 수 있다. ML5에서 제공하는 AI 모델 중 Handpose 모델을 p5 web editor 환경에서 코드를 가져와, 손을 인식할 경우와 손을 인식하지 않은 경우로 분류하여 신호를 지정한다.
학습에 필요한 코드 및 소프트웨어를 아래 압축파일을 다운로드 받은 뒤 풀어주자.
https://drive.google.com/file/d/1Lim3JNz8dfGkYBnpobHvkB4_VuIYj7NT/view?usp=sharing
이후 실습 아래 워크북 pdf 참고하여 진행 (우측 아이콘 -> 크게 보기 및 다운로드)
Handpose AI 모델 구축 및 시리얼 통신 연결하기
아두이노 측 코드에 시리얼 통신 모터 제어 코드를 추가해 준다.
위 코드가 추가된 아두이노 코드를 업로드 한다. (아래 코드 복붙)
#include <SoftwareSerial.h> //가상 시리얼 통신을 위한 라이브러리 선언
#define BT_RXD 3 // 아두이노의 4번핀을 RX(받는 핀)로 설정
#define BT_TXD 4 // 아두이노 3번핀을 TX(보내는 핀)로 설정
SoftwareSerial bluetooth(BT_RXD,BT_TXD); //블루투스 통신을 위한 설정
int RightMotor_E_pin = 5; // 오른쪽 모터의 Enable & PWM
int LeftMotor_E_pin = 6; // 왼쪽 모터의 Enable & PWM
int RightMotor_1_pin = 8; // 오른쪽 모터 제어선 IN1
int RightMotor_2_pin = 9; // 오른쪽 모터 제어선 IN2
int LeftMotor_3_pin = 10; // 왼쪽 모터 제어선 IN3
int LeftMotor_4_pin = 11; // 왼쪽 모터 제어선 IN4
//좌우 모터 속도 조절, 설정 가능 최대 속도 : 255
int L_MotorSpeed = 185; // 왼쪽 모터 속도
int R_MotorSpeed = 160; // 오른쪽 모터 속도
int R_Motor = 0;
int L_Motor = 0;
int mode = 0;
void setup() {
pinMode(RightMotor_E_pin, OUTPUT); // 출력모드로 설정
pinMode(RightMotor_1_pin, OUTPUT);
pinMode(RightMotor_2_pin, OUTPUT);
pinMode(LeftMotor_3_pin, OUTPUT);
pinMode(LeftMotor_4_pin, OUTPUT);
pinMode(LeftMotor_E_pin, OUTPUT);
Serial.begin(9600); //PC와 아두이노간 시리얼 통신 속도를 9600bps로 설정
bluetooth.begin(9600); //블루투스와 아두이노간 시리얼 통신 속도를 9600bps로 설정
Serial.println("Welcome Eduino!");
}
char s_data = 0;
void loop() {
if(Serial.available() >0)
s_data = Serial.read();
Serial.write(s_data);
if (s_data == 2){ // 손인식 할때
R_Motor = HIGH; L_Motor = HIGH; mode = 0; // 전진
}
else if(s_data == 1){ // 손 인식 안 할때
R_Motor = HIGH; L_Motor = HIGH; mode = 3; // 정지
}
if(bluetooth.available()){
char Blue_Val = bluetooth.read();
control_SmartCar(Blue_Val);
if(mode == 0){
motor_role(R_Motor, L_Motor);
}
else if(mode == 1){
Right_role(R_Motor, L_Motor);
}
else if(mode == 2){
Left_role(R_Motor, L_Motor);
}
else if(mode == 4){
left_rotation(R_Motor, L_Motor);
}
else if(mode == 5){
right_rotation(R_Motor, L_Motor);
}
else{
analogWrite(RightMotor_E_pin, 0);
analogWrite(LeftMotor_E_pin, 0);
}
}
}
void control_SmartCar(char Blue_val){
if( Blue_val == 'g' ){ // "g" 버튼, 명령 : 전진
R_Motor = HIGH; L_Motor = HIGH; mode = 0;
//Serial.print("Forward : ");
}
else if( Blue_val == 'r' ){ // "r" 버튼, 명령 : 우회전
mode = 1;
//Serial.print("Turn Right : ");
}
else if( Blue_val == 'l' ){ // "l" 버튼, 명령 : 좌회전
mode = 2;
//Serial.print("Turn Left : ");
}
else if( Blue_val == 'b' ){ // "b" 버튼, 명령 : 후진
R_Motor = LOW; L_Motor = LOW; mode = 0;
//Serial.print("Backward : ");
}
else if( Blue_val == 's' ){ // "s" 버튼, 명령 : 정지
R_Motor = HIGH; L_Motor = HIGH; mode = 3;
//Serial.print("Stop : ");
}
else if( Blue_val == 'q' ){ // "q" 버튼, 명령 : 제자리 좌회전
mode = 4;
//Serial.print("Left Rotation : ");
}
else if( Blue_val == 'w' ){ // "w" 버튼, 명령 : 제자리 우회전
mode = 5;
//Serial.print("Right Rotation : ");
}
else{
//Serial.print("Not Defined : "); // 지정하지 않은 주소입력.
}
}
void motor_role(int R_motor, int L_motor){
digitalWrite(RightMotor_1_pin, R_motor);
digitalWrite(RightMotor_2_pin, !R_motor);
digitalWrite(LeftMotor_3_pin, L_motor);
digitalWrite(LeftMotor_4_pin, !L_motor);
analogWrite(RightMotor_E_pin, R_MotorSpeed); // 우측 모터 속도값
analogWrite(LeftMotor_E_pin, L_MotorSpeed); // 좌측 모터 속도값
}
void Right_role(int R_motor, int L_motor){
digitalWrite(RightMotor_1_pin, R_motor);
digitalWrite(RightMotor_2_pin, !R_motor);
digitalWrite(LeftMotor_3_pin, L_motor);
digitalWrite(LeftMotor_4_pin, !L_motor);
analogWrite(RightMotor_E_pin, max(R_MotorSpeed*0.4,90)); // 우측 모터 속도값
analogWrite(LeftMotor_E_pin, 255); // 좌측 모터 속도값
}
void Left_role(int R_motor, int L_motor){
digitalWrite(RightMotor_1_pin, R_motor);
digitalWrite(RightMotor_2_pin, !R_motor);
digitalWrite(LeftMotor_3_pin, L_motor);
digitalWrite(LeftMotor_4_pin, !L_motor);
analogWrite(RightMotor_E_pin, 255); // 우측 모터 속도값
analogWrite(LeftMotor_E_pin, max(L_MotorSpeed*0.4,90)); // 좌측 모터 속도값
}
void left_rotation(int R_motor, int L_motor){
digitalWrite(RightMotor_1_pin, HIGH);
digitalWrite(RightMotor_2_pin, LOW);
digitalWrite(LeftMotor_3_pin, LOW);
digitalWrite(LeftMotor_4_pin, HIGH);
analogWrite(RightMotor_E_pin, R_MotorSpeed); // 우측 모터 속도값
analogWrite(LeftMotor_E_pin, L_MotorSpeed); // 좌측 모터 속도값
}
void right_rotation(int R_motor, int L_motor){
digitalWrite(RightMotor_1_pin, LOW);
digitalWrite(RightMotor_2_pin, HIGH);
digitalWrite(LeftMotor_3_pin, HIGH);
digitalWrite(LeftMotor_4_pin, LOW);
analogWrite(RightMotor_E_pin, R_MotorSpeed); // 우측 모터 속도값
analogWrite(LeftMotor_E_pin, L_MotorSpeed); // 좌측 모터 속도값
}