프로세싱 + 아두이노 서보모터 제어


프로세싱을 통해 마우스값을 아두이노로 넘겨

LED를 제어해 보았다. 

(이전글 http://eskelt.tistory.com/65  )


그와 비슷하게 이번에는 서보 모터를 제어해보자.

(서보모터제어 이전글  http://eskelt.tistory.com/8 )


일단 프로세싱에서 마우스X 값을 아두이노로 넘기고

아두이노에서 서보 라이브러리이용하여

서보모터를 동작하도록 한다.


예제에서 마우스의 움직임과 마우스의 좌표값을 

화면에 표현하기 위한 폰트를 사용하였다.

공부한 내용을 정리한 것으로

폰트 부분과 마우스의 위치를 화살표로 표시하기 위한

부분은 삭제하면 스케치는 간단하다



프로세싱 스케치

-------------------------------------------------------------------------------------------------

import processing.serial.*;   // 아두이노와 통신을 위한 시리얼 라이브러리 사용

Serial myport;                      // 시리얼통신 선언


PFont font;                         // 폰트선언


int x;

int offset = 10;                     // 마우스의 위치를 화살표로 그리기 위한 값


void setup(){

  size(256,150);

  myport = new Serial(this,Serial.list()[2],9600);     //연결된 3번째 시리얼통신 사용

  font = loadFont("Arial-Black-48.vlw");                 //폰트적용

  textFont(font,15);                                              //폰트속성

}


void draw(){

  background(204);

  line(x,0,x,150);                    // 임의의 x좌표의 수직선

  if(mouseX>x){x+=1; offset = 10;}              // 마우스가 x좌표보다 오른쪽에 있으면 offset를 10으로하고

                                                             // x값을 증가시켜 마우스값으로 이동

  if(mouseX<x){x-=1; offset = -10;}            // 마우스가 x좌표보다 왼쪽에 있으면 offset를 -10으로하고

                                                             // x값을 감소시켜 마우스값으로 이동

  fill(0);   // 글씨색

  text(x,x,145);                                         // 현재 x 값을, 좌표 (x,145) 지점에 표시 

                                                             // x값에 따라 이동하는 글씨

  text(mouseX,mouseX,mouseY-15);          // 마우스의 좌표값을 (mouseX,mouseY-10) 지점에 표시

                                                             // 마우스 포인터 보다 약간 위쪽에 마우스X좌표 표시

  line(mouseX,mouseY,mouseX+offset*3,mouseY);       // 마우스의 위치를 화살표로 표현

  line(mouseX,mouseY,mouseX+offset,mouseY-10);     // 마우스의 위치를 화살표로 표현

  line(mouseX,mouseY,mouseX+offset,mouseY+10);     // 마우스의 위치를 화살표로 표현


  myport.write(mouseX);                 // 아두이노로 마우스의 X값 보냄

}

--------------------------------------------------------------------------------------------------



아두이노 스케치

---------------------------------------------------------

#include <Servo.h>   // 서보 라이브러리 사용

    

int x ;   

Servo servoA;   // 서보 선언

void setup(){

  Serial.begin(9600);   //시리얼 통신 시작

  servoA.attach(10);    // 서보 신호핀 10번

}


void loop(){

  if(Serial.available()>0){

    x=Serial.read();

    x = map(x,0,255,0,179);   // 데이터 값을 0~179로 범위 지정

    servoA.write(x);    // 서보 작동

  }

}

---------------------------------------------------------



작동 영상



서보모터 제어


서보모터는 일정한 각도내에서만 회전을 하는 모터로 
RC비행기의 타각조절이나 휴머노이드 로봇등에서 많이 사용한다.

서보의 작동은 일정 시간 동안 신호를 보내면 그신호 펄스 폭이
서보의 작동 각도가 된다.




그림에 의하면 1.5ms동안 펄스를 보내면 서보는 90도 위치로 회전
다시 1ms동안 펄스를 보내면 서보는 0도에 위치한다.
즉 서보는 매20ms마다 신호를 받으려 기다리고
그때마다 보내는 신호의 길이에 따라 해당 각도로 회전한다.

소스 스케치
이 소스는 서보를 제어하기 위해 신호를 직접 계산함
--------------------------------------------------------------------------- 
// 키보드의 < , > ,스페이스키 서보를 제어.
// 날짜 : Created 10 December 2007
// 저자 : Brian D. Wendt  http://principialabs.com/
// 참조 : Tom Igoe의 코드를 적용함 : http://itp.nyu.edu/physcomp/Labs/Servo

int servoPin     =  2;    // 서보에 신호를 주기위한 핀
int minPulse     =  600;  // 서보에 최소신호폭 0.6ms로 계산됨
int maxPulse     =  2400; // 최대 신호폭 2.4ms로 계산됨
int turnRate     =  100;  // 키보드 조작으로 서보를 조절할때 움직이는 폭 0.1ms 
int refreshTime  =  20;   // 서보가 새신호를 받아오는 시간 간격 
  
int centerServo;         // 서보의 중앙위치 값을 저장하기 위한 변수
int pulseWidth;          // 서보의 신호폭 
int moveServo;          // raw user input 
long lastPulse   = 0;   // recorded time (ms) of the last pulse
 
void setup()  

  pinMode(servoPin, OUTPUT);  // Set servo pin as an output pin 
  centerServo = maxPulse - ((maxPulse - minPulse)/2); 
  Serial.begin(9600); // 키보드로 제어하기 위해 통신 시작
  pulseWidth = centerServo;   // 처음 켤때 서보의 위치를 중앙으로 주기위함. 
  } 
  
void loop()                   

   // 입력을 기다린다
   if (Serial.available() > 0)
  { 
    // 입력된 값을 읽는다
    moveServo = Serial.read(); 
  
    // 키보드 문자값에서, ASCII '<' 는 44, ASCII '>'는 46 , 스페이스는 32
    if (moveServo == 44) { pulseWidth = pulseWidth - turnRate; } 
    if (moveServo == 46) { pulseWidth = pulseWidth + turnRate; } 
    if (moveServo == 32) { pulseWidth = centerServo; } 
  
    // min 과 max에서 서보를 정지한다.
    if (pulseWidth > maxPulse) { pulseWidth = maxPulse; } 
    if (pulseWidth < minPulse) { pulseWidth = minPulse; } 
  } 
  
  // 서보의 펄스는 pulseWidth으로 매 20 ms 마다 갱신된다.
  // 만일 각도가 그대로 이면, 서보의 위치를 고정한다.
  if (millis() - lastPulse >= refreshTime)
 { 
    digitalWrite(servoPin, HIGH);   // 신호를 보내기 시작
    delayMicroseconds(pulseWidth);  // 신호의 간격
    digitalWrite(servoPin, LOW);    // 신호를 멈춤 
    lastPulse = millis();           // save the time of the last pulse 
  } 
}

위 소스는 어렵고 길다.
작동 원리를 알아보기 위해 작성된것이고
아두이노가 제공하는 서보 함수를 이용하면 매우 간단하다.

/*센서로 서보 제어*/
#include <Servo.h>    //서보를 사용하기 위한 해더 파일
int sensorPin = A0;   //센서핀 설정
int val = 0;   // 센서값을 저장하기 위한 변수
Servo servoA;  //서보사용을 위한 servoA 선언
void setup(){
  servoA.attach(9);  // 서보연결핀은 9
}
void loop(){
  val = analogRead(sensorPin);  // 센서에서 값을 읽어 val에 저장
  val = map(val,0,1023,0,179);   //  map함수 측정된 0~1023사이의 val 값을 0~179 값으로 변환
  servoA.write(val);    // 서보에 변환된 val값을 씀. 그 값(각도위치)에 따라 서보 작동
}
------------------------------------------------------------------------------------

작동영상





+ Recent posts