본문 바로가기

크리에이티브 프로젝트/p5.js

p5.js와 티처블머신을 활용한 아두이노 연동하기

반응형

티처블머신( Teachable Machine)은 누구나 머신러닝 모델을 쉽고 빠르고 간단하게 만들 수 있도록 제작된 웹 기반 도구입니다.

https://teachablemachine.withgoogle.com/

 

Teachable Machine

Train a computer to recognize your own images, sounds, & poses. A fast, easy way to create machine learning models for your sites, apps, and more – no expertise or coding required.

teachablemachine.withgoogle.com

 

오늘은 티처블머신을 활용하여 아두이노와 연동하는 방법에 대해 학습하겠습니다.

 

1) 티처블머신을 이용하여 모델링하기

 

여기에서 '이미지 프로젝트'를 선택합니다.

 

표준 이미지모델을 선택합니다.

 

- 클래스 이름을 변경하고 2개이상일 경우 클래스 추가를 눌러 생성합니다.,

 

- 클래스를 4개 만들었습니다.

 

- 웹캠 버튼을 눌러 카메라를 허용한 다음 길러 눌러 녹화하기를 계속 누르면서 데이터를 추가합니다.

 

- 4개의 클래스에 각각 데이터를 추가합니다.

 

- 모델학습시키기

 

- 결과 확인

 

- 모델 내보내기 한 후 모델 업로드를 누릅니다.

- 여기서 공유가능한 링크를 사용할 것입니다. 링크를 복사해서 메모장에 붙여넣기 합니다.

https://teachablemachine.withgoogle.com/models/dq7O8CBLc/

 

Teachable Machine

Train a computer to recognize your own images, sounds, & poses. A fast, easy way to create machine learning models for your sites, apps, and more – no expertise or coding required.

teachablemachine.withgoogle.com

 

 

2) 아두이노 연결

- 서보모터 : GND, VCC, 9번핀

- I2C LCD : GND, VCC, A4, A5

 

 

- 아두이노 소스코드를 업로드하고 포트번호를 기억해 둡니다.

#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16, 2);    //lcd주고 확인 후 수정 가능

Servo servo;
int servopin=9;
int angle=0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  servo.attach(servopin);
  lcd.init();  // LCD초기 설정
  lcd.backlight(); // LCD초기 설정  
  lcd.setCursor(0,0); 
}

void loop() {
  // put your main code here, to run repeatedly:
 if(Serial.available()>0){
  byte actionCode=Serial.read();
  lcd.clear();
  
  switch(actionCode){
    case 1:
      angle=180;
      lcd.print("Cell Phone");
      break;
      
    case 2:
      angle=120;
      lcd.print("Cup");
      break;
      
    case 3:
      angle=60;
      lcd.print("My Hand");
      break;

     case 4:
      angle=0;
      lcd.print("Nothing");
      break;

    default :
      break;
  }
 }
 servo.write(angle);
}

 

3) p5.js 활용하기

https://editor.p5js.org/

 

p5.js Web Editor

 

editor.p5js.org

 

- 먼저 로그인을 합니다.(구글 아이디로 로그인하면 편리함)

- index.html을 열어 <head>~</head>와 사이에  아래있는 코드를 복사하여 붙여넣기 합니다.

- 웹 serial port 연결과 머신러닝 패키지 관련 코드입니다.

    <script src="https://unpkg.com/p5-webserial@0.1.1/build/p5.webserial.js"></script>
    <script type="text/javascript" src="https://unpkg.com/ml5@0.6.1/dist/ml5.min.js"></script>

 

 

 

- index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.3/p5.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.3/addons/p5.sound.min.js"></script>
    <script src="https://unpkg.com/p5-webserial@0.1.1/build/p5.webserial.js"></script>
    <script type="text/javascript" src="https://unpkg.com/ml5@0.6.1/dist/ml5.min.js"></script>
    
    <link rel="stylesheet" type="text/css" href="style.css">
    <meta charset="utf-8" />

  </head>
  <body>
    <main>
    </main>
    <script src="sketch.js"></script>
  </body>
</html>

 

- Ctrl+S 을 눌러 저장합니다.

 

- sketch.js

const modelURL="https://teachablemachine.withgoogle.com/models/dq7O8CBLc/"

let classifier;
let serial;
let video;
let flippedVideo;
let label;
let actionNum;

function preload(){
  classifier = ml5.imageClassifier(modelURL + "model.json");
}

let port = new p5.WebSerial();

function setup() {
  port.getPorts();			// 포트 사용 가능 확인
  port.on('noport', makePortButton);	// 기존 선택한 포트가 없으면 makePortButton() 호출
  port.on('portavailable', openPort);	// 사용 가능한 포트가 있으면 openPort() 자동 호출
  createCanvas(320, 260);
  video=createCapture(VIDEO);
  video.size(320,240);
  video.hide();
  flippedVideo = ml5.flipImage(video);
  classifyVideo();
}

function draw() {
  background(0);
  image(flippedVideo, 0, 0);
  fill(255);
  textSize(16);
  textAlign(CENTER);
  text(label, width / 2, height - 4);
}

function makePortButton() {			// 포트 첫 연결 시 포트 선택 버튼 생성
  let portButton = createButton('포트 선택');	// 버튼 생성
  portButton.mousePressed(choosePort);	// 버튼 누르면 choosePort() 자동 호출
  function choosePort() {			// 콜백함수
    port.requestPort();				// 시리얼 포트 선택창 오픈
  }
}

function openPort() {				// 콜백함수
  port.open().then(initiateSerial);		// 포트를 오픈 후 initiateSerial() 자동 호출
  function initiateSerial() {			// 콜백함수
    console.log('포트 오픈');
  }
}

function classifyVideo(){
  flippedVideo = ml5.flipImage(video);
  classifier.classify(flippedVideo, gotResult);
  flippedVideo.remove();
}

function gotResult(error, results){
  if (error){
    console.error(error);
    return;
  }
  
  label = String(results[0].label);
  
  switch(label){
    case "핸드폰" :
      actionNum=1;
      break;
      
    case "컵" :
      actionNum=2;
      break;
      
    case "손" :
      actionNum=3;
      break;
              
    default:
      actionNum=4;
      break;   
  }
  port.write(actionNum);
  
  classifyVideo();
  
}

 

 

 

- 실행결과

 

반응형