[아두이노] 구부림(flex) 센서와 관절 제어

IOT/아두이노|2019. 7. 26. 09:00

[아두이노] 구부림(flex) 센서와 관절 제어



지난 시간까지 주변 사물을 관찰하는 실험을 하였는데 문득 손을 보고 손의 움직임을 관찰하다가 한번 아두이노 시각으로 표현하고 싶은더군요. 그래서 손가락 관절을 제어하는 실험에 대해 상상하다가 예전에 공부했던 손가락의 움직임을 감지 할 수 있는 센서가 떠올랐네요. 실제 구부림 센서가 없어 실제로 실험은 못하지만 구부림 센서을 대해 간단히 이야기만 하고 가상시뮬레이터로 구부림 센서를 대신 할 부품으로 가변저항을 이용하여 가상시뮬레이터에서 손가락 관절 제어 실험을 해 보겠습니다.

1. 구부림(flex) 센서


구부림 센서는 구부림의 정도에 따라서 저항값이 달라집니다. 이 값을 통해서 구부림의 각도를 계산해 낼 수 있습니다.

int val = analogRead(A0);
int angle = map(val,입력최소값,출력최대값,0,90);

위와 같이 설정하면 구부림 값에 따라 0~90도의 각도를 만들어 낼 수 있습니다. 이 값을 통해서 Servo모터의 회전 시킬 수 있습니다.

2. 손가락 관절 제어


관철의 관찰 대상은 인간의 손으로 하겠습니다.


위 사진을 보시면 집게손가락을 보시면 세개의 관절이 있습니다. 이 부분의 동작을 관찰해 볼까요.

이제 주먹을 쥐어 볼까요.



자세히 보시면 각 마디의 관절이 약 90도 각도로 회전되어 있는 걸 보실 꺼에요.

이 관찰을 통해서 여러분들은 아두이노시각으로 표현한다면 뭐가 있을까요. 각도를 제어할 수 있는 Servo모터가 떠오르지 않나요.

집게손가락의 관절의 각도를 손이 쫙 펴진 상태에서 0도라면 주먹이 쥐어지는 과정은 서서히 3개의 관절의 각도를 증가시켜 90도 회전을 하게되면 주먹이 쥐어지는 형태가 됩니다. 이 원리를 잘 이용하게 손가락의 관절 제어를 할 수 있게 되겠죠.

오늘 다루게 되는 구부림센서를 이용하여 구부림의 각도값을 통해 3개의 관절(Servo모터)을 이용하면 손가락을 움직이게 할 수 잇겠죠.

이제 좀 더 자세히 알아보도록 하죠.

3. 구부림센서를 이용한 손가락 관절 제어


  • 준비물 : Servo모터 3개, 구부림센서, 저항 1m옴, 아두이노 우노
  • 내용 : A0는 구부림센서값을 읽기 위한 핀이고, Servo모터는 5,6,7핀을 이용한다.

실제 구부림 센서가 없기 때문에 회로도만 간단히 소개합니다.


위 회로도로 만들게 된다면 구부림의 정도에 따라서 3개의 Servo모터를 회전시키면 손가락 관절을 회전시키는 결과를 얻게 됩니다.

4. 가상시뮬레이터에서 손가락 관절 제어 실험


  • 준비물 : Servo모터 3개, 가변저항 1개, 아두이노 우노
  • 내용 : A0는 구부림센서값을 읽기 위한 핀이고, Servo모터는 5,6,7핀을 이용한다.

가상시뮬레이터에서는 구부림 센서는 없습니다. 예전에 post로 이야기 했듯이 없는 부품은 유사한 같은 느낌의 부품을 이용해서 실험을 하라고 했죠. 이번에는 가변저항을 이용하여 구부림 센서의 값을 대신하면 유사한 실험을 할 수 있게 됩니다.

위 회로도에서 보는 것처럼 가변저항의 Vcc, Gnd 핀을 연결하면 가변저항을 회전시키면 1023~0의 아날로그 신호의 변화가 일어나고가 발생합니다. 반대로 연결하면 0~1023의 아날로그 신호 변화가 일어납니다. 이 부분을 주위해주세요.

5. 코딩


손가락 과절 제어는 가상시뮬레이터에서 가변저항의 값을 각도로 바꾸기 위해서는 1023~0의 아날로그 신호값을 0~90도의 각도값을 만들고 그 각도만큼 회전시키면 됩니다.

int angle = map(analogRead(A0),0,1023,0,90);  

map()함수로 0~1023의 아날로그값을 0~90의 각도값으로 변환시킵니다. angle값으로 Servo모터를 회전시키면 됩니다.

servo1.write(angle);     
servo2.write(angle);     
servo3.write(angle);     

이렇게 가변저항을 통해 얻은 회전각을 3개의 Servomotor의 회전값으로 실행시켜면 자연스럽게 손가락 관절을 움직이게 됩니다.

종합해보면,

#include <Servo.h>

Servo servo[3];
const byte servoPin[3] = {5,6,7};

void setup()
{ 
  for(int i=0;i<3;i++){
    servo[i].attach(servoPin[i]); 
    servo[i].write(0);
  }  
  delay(1000);
}

void loop()
{  
  int angle = map(analogRead(A0),0,1023,0,90);  
  for(int i=0;i<3;i++){
    servo[i].write(angle);     
  }
  delay(50);
}

손가락 관절 제어라고 했는데 거창한 코딩을 기대하고 post를 보셨다면 크게 실망하셨을 거라 생각됩니다. 이걸로 손가락 관절이 제어가 되는지 의구심을 갖을 수 있겠죠.

시뮬레이터 결과로 간단히 설명 드리겠습니다.

6. 결과





위 결과를 보면 저게 손가락 관절이야 하실 꺼에요. 손가락 위치로 한번 재 배치 해 볼까요.


위 그림이 어느정도 회전에 대한 손가락 관절을 이해하셨나요.


7. 구부림 센서의 한계


구부림 센서는 손가락 한개의 구부림 각도 한개만 만들어 냅니다. 즉, 3개의 관절을 같은 각도로 제어하기 때문에 단순한 움직임만 만들어 냅니다. 정교한 손가락 움직임을 만들어 낼 수 없습니다. 손가락 3개의 관절 중 2개의 관절만 구부려도 구부림 센서는 이 값을 가지고 3개의 관절을 동일한 각도로 회전시키는 문제가 발생합니다.

처음에는 구부림 센서와 같은 부품으로 간단히 손가락을 움직이게 하고 나중에 능력이 된다면 근육센서로 신경값을 분석하여 손가락을 움직이는 실험을 해보세요. 나중에 기회가 된다면 꼭 해보고 싶은 실험입니다. 문제는 근육센서가 비싸고 단순히 Servo모터로 손가락을 제어하는것도 좀 부자연 스럽고 어느정도 로봇손에 관련된 고급 모터 부품을 쓴다면 재미로 실험하기에는 가격 부담이 크네요.

마무리


구부림 센서를 이용한 손가락 관절 제어는 구글검색을 하시면 쉽게 post들을 찾아 볼 수 있습니다. 대개 장갑에 구부림 센서를 부착하여 장갑을 낀 상태로 주먹을 쥐면 주먹을 쥔 각도만큼 구부림 센서는 구부러지고 그 구부림 각도만큼 아두이노에서 센서값을 읽고 회전각을 만들어서 구부린 각도만큼 회전을 시키면 실제 센서가 부착된 장갑에서 손동작과 유사하게 로봇손을 움직이게 할 수 있게 됩니다.

실제로 Servo모터가 16개가 있고 다수 Servo모터를 컨트롤 할 수 있는 모터쉴드랑 다섯개의 구부림 센서가 있다면 로봇손 전부를 움직이게 하는 실험을 할 수 있을 꺼에요. 하지만 제가 가지고 있는 부품이 Servo모터 1개뿐이라 실제 관절 실험을 못해 봤네요. 하지만 가상시뮬레이터로 어느정도 유사한 실험을 할 수 있는 것에 만족합니다.

댓글()

[아두이노] 아두이노 주차장 출입구 차량차단장치

IOT/아두이노|2019. 7. 25. 09:00

[아두이노] 아두이노 주차장 출입구 차량차단장치



일상을 주제로 주변에 상황을 아두이노로 표현하는 실험을 계속 진행 중입니다. 오늘은 아파트나 일반 주차장 또는 특정 건물에 차량을 진입하는 입구 쪽에 차량 차단장치가 설치되어 있는 곳들이 많습니다. 이 차량 차단장치를 아두이노적 시각으로 한번 실험을 해보도록 하겠습니다.

1. 주차장 출입구 차량차단장치 설정



위와 같이 상황은 근접감지센서를 다른 것을 이용해야 하는데 실험에서는 초음파센서를 이용하여 근접감지를 하도록 상황을 만들고 차량이 출입구 쪽으로 다가오면 근접감지가 되고 그 감지되었을 때 차량차단막기 올라가게 됩니다. 차량차단막이 내려져 있을 때는 Red LED에 불이 들어와 있는 상태이고 차단막이 올라가면 Green LED에 불이 들어오고 차량이 통과된다는 설정입니다.

2. 아두이노 주차장 출입구 차량차단장치 회로도


  • 준비물 : 적색 LED 1개, 녹색 LED 1개, 저항 220옴 2개, 초음파센서, Servo모터, 아두이노우노
  • 내용 : 8,9번핀은 LED에 연결하고 초음파센서핀은 7번, Servo모터은 6번 핀에 연결하시오.

실제 초음파센서는 4핀이지만 가상시뮬레이터에서는 3핀 초음파센서로 7번핀으로 Trig, Echo 역활을 수행합니다.


회로도는 복잡하지 않죠. 위 회로도는 각 역활은 아래 그림으로 이해하시면 되겠습니다.


3. 코딩



사전학습으로 Servo모터와 초음파센서에 대해서 한번 읽고 오세요. 사용하실 수 있는 분들은 그냥 넘어가셔도 됩니다.

[설계]

  • 초기신호등은 적색LED에 불이 들어온 상태가 되면 차량 정지를 의미한다.
  • 초음파센서로 근접거리가 일정거리이하가 되면 차량감지로 간주한다.
  • 차량감지가 되면 차량차단막이 올라간다는 느낌으로 Servo모터를 90도 회전한다.
  • Servo모터가 90도 회전이 되었다가 간주한 시점에 "적색->녹색" 등으로 변환시킨다.
  • 차량은 통과하는데 통과가 완료되었다고 생각되는 감지 시간을 기준으로 차단만은 일정시간 유지한다.
  • 마지막 차량 감지된 시간을 기준으로 일정시간 차단막이 올라가 있다가 차량이 통과했다고 생각 되는 시간에 차단막이 내려온다는 느낌으로 Servo모터를 0도로 회전시킨다.
  • 0도 회전을 할 때 "녹색->적색"등으로 변환시킨다.(정지)

차량감지

거리를 측정은 위 초음파센서 post의 거리 계산를 함수로 거리값을 구하게 됩니다.

int CalDistance (int Pin){  //초음파센서(3핀) 예제를 그대로 외부함수로 빼냄
  pinMode(Pin,OUTPUT); //출력모드로  사용
  digitalWrite(Pin, LOW); 
  delayMicroseconds(2); 
  digitalWrite(Pin,HIGH); 
  delayMicroseconds(10); 
  digitalWrite(Pin,LOW);   
  
  pinMode(Pin,INPUT);    //입력모드로 사용
  int duration = pulseIn(Pin, HIGH);  
  int distance = duration / 57.5;  //가상시뮬레이션의 오차율을 줄이기 위해 이걸로 테스트 함.
  return distance; //거리값 리턴
}

거리를 구하게 되면 차량이 감지판정은 if문으로 만든다.

if(m_distance<50){ //50cm미터 미만일 때 차량 감지로 간주             
  차량감지 후 동작;
}

차량이 감지 후 동작은

  if(m_distance<50){   //50cm미만일 때 차단막 올리기 동작       
    if(state==false){  //초기값은 state=false상태로 처음에는 이 if조건문이 무조건 참이 된다.
      servo.write(90); //감지 되었기 때문에 Servo모터 90도 회전
      delay(2000);   //2초 동안 강제로 Servo모터가 회전하도록 설정
      state=true;     //다시 이 if조건문을 수행할 필요가 없기 때문에 state=true 설정     
      digitalWrite(rPin, LOW); //차단막이 올라갔으니 적색등 끄기
      digitalWrite(gPin, HIGH); //차량 통행하도록 녹색등 켜기
    }
    timeVal=millis(); //마지막 차량 감지된 시간을 저장함
  }  
  if(state==true){ //차단막 내리기 동작
    if(millis()-timeVal>=2000){ //마지막 차량 감지된 시간을 기준으로 차단막 유지시간이 지났는가 체크
      servo.write(0); //차단막 내리기
      state=false; //차단막이 내려졌으니 이 if조건문을 수행할 필요가 없기 때문에 state=fasle 설정
      digitalWrite(gPin, LOW); //차단막이 내려오니깐 녹색등은 끄기
      digitalWrite(rPin, HIGH); //차량 정지하도록 적색등 켜기
    }    
  } 

주석을 일일히 다 달아놓았으니깐 주석을 살펴보시기 바랍니다. 왜! if문을 state의 상태값으로 두가진 차단막 올리기/내리기 동작을 구분하였을 까요. 두 동작을 구분을 지어서 동작하게 하기 위해서요. 자세히 보시면 만약 차단막이 올라간 상태에서 계속 현재 차량이 감지되거나 계속 새로운 차량이 들어올 경우는 계속 차단막 올리는 명령을 내려야 합니다. 이미 올라갔는데 구지 반복 명령을 내릴 필요는 없이 현상태만 유지하면 됩니다. 그래서 if문으로 올라갔으면 내려가는 상황만 체크하면 되지 올라가는 상황을 동작할 필요없는 없습니다. 여기서, timeVal은 올라가는 상황 코딩 안에 다 넣지 않고 밖에다 빼낸 이유는 계속 초음파센서로 감지했을 때 마지막으로 감지된 시간을 기준으로 차단막의 유지시간을 결정하게 하기 위해서 입니다.

종합해보면,

#include <Servo.h>

Servo servo;
const byte servoPin = 6;
const byte pingPin = 7;
const byte gPin = 8;
const byte rPin = 9;
int m_distance=0;
boolean state = false;
unsigned long timeVal=0;

void setup()
{
  pinMode(gPin, OUTPUT);
  pinMode(rPin, OUTPUT);  

  servo.attach(servoPin); 
  servo.write(0);
  delay(1000);
  
  digitalWrite(rPin, HIGH);
}

void loop()
{
  m_distance=CalDistance(7);  //초음파센서로 거리계산함수  
  if(m_distance<50){            
    if(state==false){
      servo.write(90);
      delay(2000); 
      state=true;          
      digitalWrite(rPin, LOW);
      digitalWrite(gPin, HIGH);
    }
    timeVal=millis();
  }  
  if(state==true){
    if(millis()-timeVal>=2000){
      servo.write(0);
      state=false;
      digitalWrite(gPin, LOW);
      digitalWrite(rPin, HIGH);
    }    
  }  
}

int CalDistance (int Pin){  //초음파센서(3핀) 예제를 그대로 외부함수로 빼냄
  pinMode(Pin,OUTPUT); //출력모드로  사용
  digitalWrite(Pin, LOW); 
  delayMicroseconds(2); 
  digitalWrite(Pin,HIGH); 
  delayMicroseconds(10); 
  digitalWrite(Pin,LOW);   
  
  pinMode(Pin,INPUT);    //입력모드로 사용
  int duration = pulseIn(Pin, HIGH);  
  int distance = duration / 57.5;  //가상시뮬레이션의 오차율을 줄이기 위해 이걸로 테스트 함.
  return distance; //거리값 리턴
}

loop()함수 내 로직만 설계에 맞게 코딩만 하면 오늘 코딩의 전부입니다. loop()함수 내 코딩은 몇줄 안되지만 설계의 내용을 다 포함되어 있네요. 글보다 코딩이 더 짧은 케이스네요.

4. 결과


가상시뮬레이터에서 결과입니다.


5. 실제 테스트


정상적으로 동작하는지 실제로 구현해 봤네요.

1) 아두이노 주차장 출입구 차량차단장치 회로도


4핀짜리 초음파센서로 대충 실제 제작 모습과 동일하게 디자인 했네요.


위 회로도를 실제 배치하고 선을 연결하니깐 아래와 같은 모습으로 좀 지져분하게 되었습니다.


2) 코딩



위의 가상시뮬레이터 코딩에서 newPing 라이브러리를 사용해서 그부분만 수정했습니다. 그리고 초음파센서가 4핀이니 trig, echo 핀을 정확하게 지정해 줘야 합니다.

코딩은 가상시뮬레이터 소스에서 newPing 라이브러리를 이용한 방식과 4핀 초음파센서 부분만 수정하면 됩니다.
그리고 주의할 점은 실제 초음파센서에서는 거리 측정값이 오류가 발생합니다. 이 오류를 해결하기 위해서 초음파센서값에 대한 평균값을 구해서 오류값을 막을 수 도 있지만 간단하게 오류값을 무시하는 방식을 취했습니다.

  if(m_distance>오류값 && m_distance<감지거리){       
      동작;
  }

제가 쓰는 초음파센서는 가끔 0과 10이하의 값들이 찍히네요. 그래서 실험에서는 10이상의 값들만 거리 판정을 내렸네요. 만약 결과가 정상적으로 나오지 않는다면 거리측정값을 시리얼통신을 통해 시리얼모니터로 그 결과를 찍어보시고 여러분들이 원하는 값으로 수정해 주시면 됩니다.

수정해보면,

#include <NewPing.h>
#include <Servo.h>

Servo servo;
const byte servoPin = 7; 
const byte gPin = 8;
const byte rPin = 9;
int m_distance=0; //거리
boolean state = false; //차단막 제어를 위한 상태값
unsigned long timeVal=0;

NewPing sonar(6, 5, 200); // (Trig, Echo. 거리제한)

void setup() {
  
  Serial.begin(9600);
  pinMode(gPin, OUTPUT);
  pinMode(rPin, OUTPUT);  

  servo.attach(servoPin); 
  servo.write(0);
  delay(1000);
  
  digitalWrite(rPin, HIGH);
}

void loop() {  
  delay(50);            
  m_distance=sonar.ping_cm();  //초음파센서로 거리계산함수  
  Serial.println(m_distance);
  if(m_distance>10 && m_distance<20){  //20cm는 의미가 있는 것은 아닙니다.
    if(state==false){
      servo.write(90);
      delay(2000); 
      state=true;          
      digitalWrite(rPin, LOW);
      digitalWrite(gPin, HIGH);      
    }
    timeVal=millis();
  }  
  if(state==true){
    if(millis()-timeVal>=3000){
      servo.write(0);
      state=false;
      digitalWrite(gPin, LOW);
      digitalWrite(rPin, HIGH);
    }    
  } 
}

3) 결과


10cm이하는 차량감지로 판정을 하지 않습니다. 그리고 20cm미만일 때 차량감지 파전을 내렸네요. 스마트폰으로 촬영하기 위해서 거리값을 최대한 줄여서 실험 했네요.


마무리


최근에 계속 아두이노적 시각으로 주변환경을 관찰하면서 하나씩 post 주제를 선정하고 있네요. 지하주차장에 차량차단막이 되어 있는 곳을 들어 갈 때 차량을 감지하고 차단막이 올라가면서 옆에 신호등이 "적색->녹색" 등으로 바뀌는 상황을 보면서 "아! 이걸 주제로 표현해봐야지!"하고 이렇게 실험하게 되었네요.

여러분들도 한번 주변환경을 관찰하고 저처럼 실험을 해보세요.


댓글()

[아두이노] RFID-RC522 + Servo Motor 제어

IOT/아두이노|2019. 5. 7. 09:00

[아두이노] RFID-RC522 + Servo Motor 제어



지난 시간에 RFID-RC522를 아두이노에 연결하여 제대로 인식하는지에 대해 예제를 통해 간단히 테스트를 하였습니다. MFRC522 라이브러리에서 초기 선언하는 세팅 부분만 간단히 살펴 보았기 때문에 뭔가 제어하는 실험이 부족한 것 같아서 오늘은 Servo Motor를 같이 연결하여 RFID-RC522를 제어하는 실험을 하고자 합니다. 어제 배웠던 내용에서 크게 변화 된 것은 없습니다. 단지 카드 UID 값을 읽고 그 값에 일치 하면 Servo Motor가 특정 각도로 회전이 일어나도록 하는 실험을 하고자 합니다. 일상에서의 도어락이나 전철을 탈때 출입 통로, 회사 출입 통로 등의 카드를 대면 인식하고 출입을 할 수 있도록 문을 열어주는 동작과 느낌을 실험하고자 Servo Motor의 Open 회전값과 Close 회전값을 주어 비슷한 느낌을 표현 하였습니다.


1. RFID-RC522 + Servo Motor 회로도



  • 준비물 : RFID-RC522, Servo Motor, 피에조부저, 아두이노우노
  • 내용 : SPI 통신을 할 수 있게 핀은 연결하고 Servo Pin 7번, 피에조부저 6번으로 연결해 보자.
  • 지난시간 회로도 참고 : RFID-RC522 제어(아두이노)


출처 : Fritzing

RFID-RC522 회로도가 좀 복잡해 보일 꺼에요. 지난 시간에 RFID-RC522 회로도에서 Servo Motor와 피에조부저 핀을 추가 하시면 됩니다. 오늘 회로도를 보고 선을 연결하지 마시고 링크 걸린 지난 시간의 회로도를 보고 회로도 선을 연결한 뒤에 오늘사용하는 7번 Servo 핀과 6번 피에조 핀만 연결하면 되니깐 그렇게 어렵지 않을 꺼에요.

2. 코딩



MFRC522

#include <SPI.h>
#include <MFRC522.h>
  • MFRC522 mfrc522(SS_PIN, RST_PIN) : MFRC522 인스턴스화
  • SPI.begin() :SPI bus 초기화
  • mfrc522.PCD_Init() : MFRC522 card 초기화
  • mfrc522.PICC_IsNewCardPresent() : 새카드 확인
  • frc522.PICC_ReadCardSerial() : 하나의 카드읽기 확인
  • rfid.uid.uidByte[] : 읽은 카드 키값이 들어 있음

피에조 부저

  • tone(tonePin ,음,음길이) : 음 시작
  • noTone(tonePin ) : 음 중지

Servo Motor

#include <Servo.h>
  • Servo servo : 서보모터 객체 선언
  • servo.attach(서보핀) : 서보 모터에 출력을 담당할 핀 선언
  • servo.write(회전각) : 회전각 만큰 서보모터를 회전 시킴

시리얼 통신

  • Serial.begin(9600) : 시리얼 통신 시작(9600 통신속도)
  • Serial.println(값) : 시리얼모니터 출력
  • Serial.available() : 시리얼통신으로 데이터가 들어놨는지 상태 확인
  • Serial.parseInt() : Int형으로 데이터를 읽음

지난 시간에 이여서 오늘도 위 함수 부분은 그대로 Post에 남겨 뒀습니다. 지난 시간의 Post를 왔다 갔다 하실 필요 없이 오늘 Post만 보시고 코딩을 생각할 수 있게 그대로 가져 왔네요.

[소스] MFRC522의 예제 중 하나( 출처 : miguelbalboa의 라이브러리)

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN         9       
#define SS_PIN          10      

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

void setup() {
    Serial.begin(9600);     // Initialize serial communications with the PC
    while (!Serial);        // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
    SPI.begin();            // Init SPI bus
    mfrc522.PCD_Init();     // Init MFRC522
    mfrc522.PCD_DumpVersionToSerial();  // Show details of PCD - MFRC522 Card Reader details
    Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}

void loop() {
    // Look for new cards
    if ( ! mfrc522.PICC_IsNewCardPresent()) {
        return;
    }

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial()) {
        return;
    }

    // Dump debug info about the card; PICC_HaltA() is automatically called
    mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}

지난 시간에 라이브러리에 있던 예제 소스입니다. 이 소스를 기반으로 Servo Motor를 제어 하겠습니다. 우선 위 소스를 DumpInfo 예제를 한번 실행 시켜 주세요.

Card UID: 55 AF 07 88

Card UID의 값을 확인 하세요. 참고로 제가 실험하는 Card UID 값하고 여러분이 실험하는 Card UID는 다릅니다. 이 Card UID로 실험하기 때문에 한번 실행해서 자신의 Card UID를 알아내야 합니다. 확인이 되면 이 Card UID 값을 배열 변수로 저장 하세요.

byte CardUidByte[4] = {0x55, 0xAF, 0x07, 0x88};

참고로, 숫자가 알파벳이 나오면 16진수라고 여기세요. 여기서 그냥 숫자를 기입하시면 안되고 앞에 '0x'을 꼭 붙여주셔야 이 수가 16진수이구나 하고 프로그램이 인식합니다. 이렇게 해서 비교 할 Card UID값을 저장해 놓았습니다.

카드를 읽게 되면 그 값은 어디에 들어 있을까요.

mfrc522.uid.uidByte[]

이곳에 담겨져 있습니다. 4개의 UID 숫자값이 Card UID 값을 가지고 있으니 mfrc522.uid.uidByte[0] ~ mfrc522.uid.uidByte[3] 까지해서 그 값을 가지고 있습니다. 그러면, IF문으로 해서 저장된 값과 비교하면 됩니다.

  if (mfrc522.uid.uidByte[0] == CardUidByte[0] && mfrc522.uid.uidByte[1] == CardUidByte[1] &&
        mfrc522.uid.uidByte[2] == CardUidByte[2] && mfrc522.uid.uidByte[3] == CardUidByte[3] ){
                읽어온 Card UID 값과 저장된 Card UID값이 일치하면 참;
                명령문;
  }

이렇게 해서 카드를 RFID-RC522에 대면 두 Card UID 값을 서로 비교하게 됩니다. 그리고 일치하면 if문 안의 명령문을 수행하게 됩니다.

코딩은 거의 다 했습니다. 이제는 Servo Motor를 회전 시켜야 겠죠. 카드의 UID가 일치하니깐 Servo Motor가 Open 시키는 의미로 일정 각도로 회전 시키는 동작과 다시 카드를 RFID-RC522에 대면 Servo Motor가 Close 시키는 의미로 원래 각도로 회전 시켜는 동작을 표현 할 에정입니다. Card를 대면 Open or Close가 교차로 반복되는 실험입니다.

이 동작을 수행하기 위해서는 어떻게 코딩해야 할까요.

boolean state = false;

이렇게 하나의 ServoMotor의 상태값 변수를 만들어 놓습니다. 그리고 나서 아래와 같은 코딩을 하면 됩니다.

  if (mfrc522.uid.uidByte[0] == CardUidByte[0] && mfrc522.uid.uidByte[1] == CardUidByte[1] &&
        mfrc522.uid.uidByte[2] == CardUidByte[2] && mfrc522.uid.uidByte[3] == CardUidByte[3] ){
          
          state=!state;  //Servo Motor(Open or Close)
                
          if(state == true){
           Serial.println("Open");
           servo.write(180);
           delay(1000);
          }
          else{           
           Serial.println("Close");
           servo.write(0);
           delay(1000);
          }
          delay(2000);              
  }

초기 state은 false 상태이고 Cade UID 값이 일치하면 state은 반전 true가 되어 다음 if문에서 "state == ture"이면 참이니깐 "Open"으로 Servo Motor를 180도 회전 시키고 1초 대기 했다가 다시 연속으로 카드값이 인식하지 못하도록 2초동안 딜레이 시간을 추가로 더 연장 했습니다. 총 3초 동안은 Card가 인식되지 못하게 했습니다. 3초가 지난 후 Card가 다시 RFID-RC522에서 인식하면 state은 !state로 반전으로 state은 false가 되어 다음 if문 "state == ture"가 거짓으로 else 이하 문장을 수행 합니다. 그러면 "Close"로 Servo Motor은 0도로 원래 각도로 회전 되어 돌아오게 됩니다. Card가 RFID-RC522에 대면 교차로 "Open" 과 "Close"가 반복 됩니다.

이렇게 해서 Card로 Servo Motor를 회전 시킬 수 있게 되었습니다.

여기서, 추가로 Card가 읽혔는지 확인 할 방법이 없습니다. Servo Motor가 회전 되었을 때 확인이 됩니다. 즉, 카드를 Servo Motor가 회전 될 때 까지 RFID-RC522에 대고 있어야 한다는 소리가 됩니다. 좀 불편하죠.

그래서, 카드를 읽은 순간 그때 뭔가 메세지를 외부로 보여준다면 이 문제가 해결 할 수 있습니다. 그 역할을 소리로 표현하기 위해서 피에조부저를 이용하고자 합니다.

  // 새 카드 확인
  if ( ! mfrc522.PICC_IsNewCardPresent()) return; 

  // 카드 읽기
  if ( ! mfrc522.PICC_ReadCardSerial()) return;
    
  tone(tonePin ,523,1000/8);     // 도음으로 8분음표(음길이)
  delay(1000/4*1.30);             
  noTone(tonePin ); 

이렇게 카드가 읽기와 카드를 비교하기 전 사이에 사이에 피에조부저의 음이 울리게 하면 쉽게 확인이 되겠죠.

종합해 보면,

[소스]

#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h>

const int RST_PIN = 9;
const int SS_PIN = 10;

MFRC522 mfrc522(SS_PIN, RST_PIN);   // MFRC522 인스턴스

byte CardUidByte[4] = {0x55, 0xAF, 0x07, 0x88}; //card UID 
boolean state = false; //Servo Motor 상태값

Servo servo;
const int SERVO_PIN = 7;
const int TONEPIN = 6;

void setup() {
  Serial.begin(9600);  
  while (!Serial);     
  SPI.begin();         //SPI 시작
  mfrc522.PCD_Init();  //MFRC522 card 초기화
  Serial.println(F("Warning: this example clears your mifare UID, use with care!"));

  servo.attach(SERVO_PIN);
  servo.write(0);
  delay(50);
}

void loop() {
  // 새 카드 확인
  if ( ! mfrc522.PICC_IsNewCardPresent()) return; 

  // 카드 읽기
  if ( ! mfrc522.PICC_ReadCardSerial()) return;

  //카드 확인 메세지 음
  tone(tonePin ,523,1000/8);     // 도음으로 8분음표(음길이)
  delay(1000/4*1.30);             
  noTone(tonePin ); 

  //읽은 Card UID와 등록된 Card UID가 일치하는 확인
  if (mfrc522.uid.uidByte[0] == CardUidByte[0] && mfrc522.uid.uidByte[1] == CardUidByte[1] &&
        mfrc522.uid.uidByte[2] == CardUidByte[2] && mfrc522.uid.uidByte[3] == CardUidByte[3] ){
   
         state=!state;    
                 
         if(state == true){
           Serial.println("Open");
           servo.write(180);
           delay(1000);
          }
          else{
           Serial.println("Close");
           servo.write(0);
           delay(1000);
         }
         delay(2000);
   }  
}

3. 결과



4. 추가 코딩


위 코딩은 약간 도어락 같은 느낌 이였다면 출입문일 경우는 카드로 열고 닫고를 안하고 한번 대면은 열리고 나서 일정시간이 지나면 닫히게 됩니다. 출입문 경우는 어떻게 코딩할까요.

위 소스에서 한 부분만 수정하면 됩니다.

  //읽은 Card UID와 등록된 Card UID가 일치하는 확인
  if (mfrc522.uid.uidByte[0] == CardUidByte[0] && mfrc522.uid.uidByte[1] == CardUidByte[1] &&
        mfrc522.uid.uidByte[2] == CardUidByte[2] && mfrc522.uid.uidByte[3] == CardUidByte[3] ){
   
           Serial.println("Open");
           servo.write(180);
           delay(5000);
           Serial.println("Close");
           servo.write(0);
           delay(1000);                 
   }  

이렇게 수정하시면 끝납니다. 실험에서는 5초 동안 열렸다가 다시 닫히는 걸로 했는데요. 실제 출입문이면 이러지는 않겠죠. 적어도 수십초는 열려 있다가 닫혀야 겠죠. 아니면 초음파 센서같은 인간 감지 센서를 이용하여 지나 가면 자동으로 닫히게 하면 되겠죠. 그렇게 하자면 부품이 추가로 늘어나고 오히려 오늘 전달하고자 하는 의미가 제대로 전달되지 않기 때문에 이정도 까지만 하겠습니다.

[결과]


마무리


RFID-RC522 라이브러리는 쉽지 않지만 간단한 부분만 가져다가 응용하면 그래도 재밌는 표현들을 할 수 있습니다. 여러분들도 한번 이 RFID-RC522 모듈을 구하셔서 실험을 해보셨으면 합니다. 가격도 비싸지 않고 싼편이라서 괜찮은 실험 도구라고 생각 되네요.

아두이노우노에서 실험하면 SPI 통신을 하기 때문에 사실 다른 부품을 추가 할 자리가 많지 않습니다. 그럴 때는 두개 이상의 아두이노로 통신을 통해 제어하면 좋은데 그 실험을 하려면 2대정도 있어야 하는데 한대 뿐이라 아쉽네요.

아무튼 오늘 배운 내용을 토대로 다른 부품 특징들을 머리속에서 떠올려서 RFID-RC522와 연결하는 상상을 한번 해보셨으면 합니다.


댓글()

[아두이노] 서보모터를 리모콘(IRremote)으로 제어

IOT/아두이노|2019. 3. 15. 09:00

[아두이노] 서보모터를 리모콘(IRremote)으로 제어 



이번 내용을 지금까지 복습한 내용들을 종합해서 사용해보는 시간을 갖도록 하겠습니다. 총 3개의 주제를 하나로 묶어서 회로도를 구성할 예정입니다. 다 합쳐진 모습은 좀 복잡해 보일 수 있지만 개별 포스트 내용을 참고하시면 어렵지 않을거라 생각됩니다. 전체 코딩한 내용을 보면 이런걸 어떻게 코딩을 초보분들이 할 수 있냐고 생각 될 수 있지만 따로 각 주제별로 접근하면 단순한 코딩입니다. 그걸 합쳐놓아서 복잡해 보일 뿐입니다. 위에 참고자료 3개의 포스팅한 내용을 한번 다시 읽고 이번 포스팅을 보시면 "그냥 합쳐놓은거네!" 이라고 말할 꺼에요.

1. IRremote + Servo모터 + LCD16x2 소스


IRremot 소스

#include <IRremote.h>
 
int IRpin = 11;  
IRrecv irrecv(IRpin);
decode_results results;

void setup()
{
  irrecv.enableIRIn(); // 리모콘 시작
}
void loop()
{
  if (irrecv.decode(&results)) //리모콘 누른값이 없다면 패스
    {
     
      "results.value의 키값을 사용할 예정";
            
     irrecv.resume(); // 다음값
    }
}

Servo모터 소스

#include <Servo.h> 
 
Servo servo; 
int SERVO_PIN = 10;

void setup() 
{ 
    servo.attach(SERVO_PIN); 
}

void loop() 
{
    "servo.write(180) 함수로 서모모터회전시킬 예정";
}

LCD16x2 소스

#include <LiquidCrystal.h>

//LiquidCrystal(rs, enable, d4, d5, d6, d7) 
LiquidCrystal lcd(3, 4, 9, 10, 11, 12);

void setup()
{
  lcd.begin(16,2);
  lcd.setCursor(0, 0);
  lcd.print("Servo Angle :");
  delay(1000);  
}

void loop() {
  lcd.setCursor(0, 1);
  "lcd.print("각도")함수로 각도값을 출력할 예정";
}

2. 회로도 구성


  • 준비물 : IR Sensor, 리모콘, 서보모터 1개, LCD16x2 1개, 저항 220옴 1개, 가변저항 10k옴 1개, 아두이노우노, 뻥판
  • 내용 : 리모콘을 눌러서 서보모터를 회전 시키고 LCD16x2에 회전각을 출력시켜보자.


참 쉽죠. 회로도 별거 없지요. 그러면 욕먹겠지요. 지금까지 배운 서보모터 제어, LCD16x2 제어, 리모콘 제어로 총 3편의 포스팅 내용을 토대로 간단히 회로도를 구성해 봤습니다. 개별적으로 포스팅한 내용 보시면 이 회로도 구성은 별거 없다는 것을 아마 아실꺼에요. 다 합쳐놓으니깐 좀 복잡해 보일뿐이죠. 실상은 간단합니다.

만약 LCD16x2 I2C 로 출력한다면 더 간단해 집니다. 해보고 싶은분은 LCD16x2 I2C 제어편을 보시고 실제로 실험을 도전하세요.

3. 코딩


  • 사용함수 : 리모콘 함수, 서보모터 함수, LCD16x2 함수
  • 내용 : 리모콘를 화살표키를 눌러 10도씩 회전 시키고 그 결과를 LCD 16x2로 출력해보자.

[ 리모콘 함수 ]

  • irrecv.enableIRIn() : 리모콘 시작
  • irrecv.decode(&results) : 키가 눌러진지 확인
  • irrecv.resume() : 다음값

[ 서보모터 함수 ]

  • servo.attach(사용핀) : 사용핀을 서보모터 제어로 사용
  • servo. write(각도) : 각도로 회전시킨다.

[ LCD16x2 함수 ]

  • lcd.begin(가로,세로) : 화면나누기
  • lcd.setCursor(0, 0) : LCD16x2 모니터의 커서의 위치
  • lcd.print(출력값) : LCD16x2에 값을 출력

설계

1. 리모콘의 화살표 위아래 버턴만 사용한다.
2. 리모콘의 키값을 읽는다.

if (irrecv.decode(&results)) {                     
  키가 눌러졌다면 => results.value 값에 키값이 있겠죠
}

3. 각도변수에 화살표 키값을 위아래 누를때 증가/감소 시켜서 각도값을 만들어 낸다.

    if(리모콘키값 == 증가키값){  
      if(m_Angle<180){ //0~180도로 제한으로180도 이상 증가하면 안되니깐 각도 증가는 180보다 작아야함
        m_Angle=m_Angle+10; or m_Angle+=m_Angle;  =>  같은 표현
      }          
    }
    else if(리모콘키값 == 감소키값){ //0~180도 제한으로 0도 이하로 감소하면 안되니간 각도 감소는 0보다 커야함 
      if(m_Angle>0){
        m_Angle=m_Angle-10; or m_Angle-=m_Angle; => 같은 표현
      }      
    }  
<

4. LCD16x2에 각도값을 출력한다.

lcd.setCursor(0, 1); //두번째 줄에 첫칸에 커서 위치
lcd.print("                ");  //두전째 줄에 이전 기록된 값을 지우기 공백 16칸
lcd.setCursor(0, 1); //두번째 줄에 첫칸에 커서 위치한 이유 데이터를 기록할 위치를 다시 잡아줘야함
lcd.print(m_Angle); // 두번째 첫칸에 각도값이 출력됨

5. 서보모터에 각도변수에 저장된 값을 출력(회전) 한다.

servo.write(m_Angle);

간단하지요.

전체적으로 코딩을 하면

#include <IRremote.h>
#include <LiquidCrystal.h>
#include <Servo.h> 

//1
Servo servo; 
int SERVO_PIN =10;
int m_Angle = 0;

//2
//LiquidCrystal(rs, enable, d4, d5, d6, d7) 
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

//3
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{  
  servo.attach(SERVO_PIN);
  
  irrecv.enableIRIn(); 
  
  lcd.begin(16,2);
  lcd.setCursor(0, 0);
  lcd.print("Servo Angle : ");
  
  
}

void loop() {
  
  if (irrecv.decode(&results)) {                     
   
     // Serial.println(results.value);
    
    if(results.value == 0xFD50AF){  //16601263 or 0xFD50AF
      if(m_Angle<180){
        m_Angle=m_Angle+10; // m_Angle+=m_Angle;
      }          
    }
    else if(results.value == 0xFD10EF){ //16584943 or 0xFD10EF
      if(m_Angle>0){
        m_Angle=m_Angle-10; // m_Angle-=m_Angle;
      }      
    }  
   
    lcd.setCursor(0, 1);
    lcd.print("                ");   
    lcd.setCursor(0, 1);
    lcd.print(m_Angle);
  
    
    irrecv.resume(); 
  }
  servo.write(m_Angle);
  delay(100);
}

4. 결과


리모콘 화살 키를 눌렀을때 결과입니다. 각도 0도에서 각도 10도가 증가하고 LCD16x2에 각도 값이 출력되고 서보모터는 10도 회전하는 장면 입니다.


동영상으로 제가 실험한 장면을 녹화 했네요. 어떤식으로 진행 했는지 보시면 그리 어렵지 않을꺼에요. 3개의 주제를 다 합치고 또 코딩하는 부분 까지 전부 다 녹화하다보니 꽤 길어졌네요. 동영상이 너무 길기 때문에 결과 이미지만 보시고 대충 이렇게 결과가 나오는 구나 정도로만 이해하시도 됩니다.


마무리


이번 포스팅은 응용편으로 각 하나의 부품을 제어하다 보면은 너무 쉽고 간단해서 이걸로 뭘 할 수 있지 생각하는 분들이 아마 있을거에요. 각 부품 포스팅 마다 예제소스도 너무 단순하게 표현해서 뭘 만들어 볼려는 분들은 부품간 연결이 이미지화 하기가 좀 힘드실꺼에요. 그래서 이번에는 좀 고려하고 코딩해야하는 부분이 있는데 그걸 다 무시하고 읽기 편하게 코딩을 배치했네요. 원래를 코딩을 하실때 이렇게 배치하시면 안되고요. 변수와 객체를 체계적으로 선언하고 코딩도 각 경계의 구분을 명확하게 하고 너무 한곳에 집중 코딩하기 보다는 외부함수로 빼서 분산시켜서 loop()함수 내 코딩은 최소화로 간결하게 가독성을 높이는 코딩을 해야 합니다. 그걸 다 무시하고 우선 초보분들은 가독성 위주로 코딩 했네요.

오늘은 서보모터랑 LCD16x2 모니터를 사용하여 리모콘을 제어했네요. 여러분들오 한번 지금까지 포스팅한 부품 중에 맘에 드는 것을 골라서 한번 만들어 보세요. LED가 맘에 든다면 LED 부품을 사용하여 숫자키 값에 따라서 전원 스위치로 활용하여 LED를 켜고 끄기를 할 수 있습니다. 또는 RGB LED로 리모콘 키값을 이용해서 컬러값을 만들어내서 RGB LED의 색을 다양하게 표현하는 실험을 할 수 있을거에요.

그외도 많지만 한번 상상의 나래를 펼쳐 보세요.


댓글()

[아두이노] 서보모터 제어

IOT/아두이노|2019. 2. 19. 09:18

[아두이노] 서보모터 제어



이전 시간까지는 칩과 관련해서 제어를 하다보니 복잡한 주제를 포스팅 했었습니다. 이번에는 좀 쉬운 주제를 다루고자 합니다. 기본 서보모터 동작 제어만 다루기 때문에 별거 아니라고 생각 할 수 있지만 서보모터 제어는 나중에 아두이노로 작품을 만들때 가장 많이 사용하는 부품입니다. 그리고 사용 목적에 따라서 코딩 능력을 필요로 하는 부분이기도 하기 때문에 사용목적에 따라 좀 어려울 질 수 있는 부품이기도 합니다. 하지만 오늘 포스팅은 단순한 제어를 통해 서보모터를 체엄하도록 하죠.

1. 서보모터



서보모터는 Vcc(5V), Gnd, Signal(입력신호)로 3핀으로 구성되어 있습니다. 아두이노에서 Signal핀에 신호를 보냄으로써 각도를 제어하게 됩니다.

2. 회로도 구성


  • 준비물 : 서보모터 1개, 아두이노우노
  • 내용 : 서보모터 회전 시키자


가장 간단한 회로도 입니다. Vcc은 5V에 Gnd은 Gnd에 Signal은 9핀에 연결하면 완료입니다. 원래 모터제어를 할때는 모터쉴드보드가 필요합니다. 하지만 서보모터의 경우는 아두이노에서 직접 제어해도 됩니다.

3. 코딩


  • 사용함수 : attach(사용핀), write(각도), writeMicroseconds(각도시간값)
  • 내용 : 간단히 180도 회전만 시키자.

설계

(1) 서보모터객체 선언

서보모터를 사용하기 위해서는 제어함수들이 있는 Servo클래스를 객체로 선언합니다. 이말은 예전에 변수 선언과 같은 의미로 생각하시면 됩니다. Servo 클래스를 하나의 변수에 저장되었다고 생각하시면 됩니다.

#include <Servo.h> 
Servo servo1; 

Servo.h 파일에 있는 Servo 클래스를 servo1이라는 객체변수로 선언합니다. 그래서 servo1 객체를 통해서 Servo 클래스 안에 함수들을 사용하게 됩니다. 쉽게말해서 servo1.함수() 이렇게 Servo클래스의 함수를 사용할 수 있게 됩니다.

(2) 서보모터객체 연결

servo1.attach(사용핀);
servo1.attach(사용핀,min,max); //Ardunio min = 544, max=2400

attach()함수는 해당핀을 서보모터를 제어하는 핀으로 사용하겠다는 의미로 받아 들이시면 됩니다. 여기서, 두가지 방식이 있는데 첫번째, 사용핀만 인자로 넘겨주면 기본값으로 자동으로 세팅됩니다. 두번째, min, max로 범위를 따로 지정해 줄 수 있습니다. 두번째 방식이 좀 더 서보모터를 정교하게 제어할 수 있습니다.

과거 tinkercad.com 사이트로 옮기전 사이트에서는 서보모터가 다른 종류가 한개 더 있었는데 그 모터에서는 min, max값을 1000, 2000으로 줘서 1500일때 90도 회전이였습니다. 가상시뮬에터에서는 그냥 544, 2400으로 맞춰서 실험했네요. 서보모터마다 제어하는 각도가 차이가 있기 때문에 조정 작업이 필요합니다. 그래서 범위를 지정해서 하실때는 사용하시는 서보모터의 종류에 따라 다르니깐 꼭 보정을 하셔야 합니다.

(3) 서보모터객체 제어

servo1.write(180); 
servo1.writeMicroseconds(2400);

여기에서 write(각도)로 제어하시면 서보모터 기종에 따라서 약간 차이를 보이게 됩니다. 정확하게 제어가 안될 수 있습니다. 하지만 writeMicroseconds(2400)로 제어하시면 오차율을 줄일 수 있습니다. 하지만 보정을 해야하기 때문에 좀 귀찮은 점이 있지요.

(3) delay()함수 사용

delay(2000);

180도를 회전 시킬려고 하는데 일정 시간이 필요합니다.

만약에,

servo1.write(180); 
delay(500);
servo1.write(0); 
delay(500);

delay(500)으로 할 경우 0.5초동안 180도로 갈려고 회전하는 도중에 딜레이 시간이 끝나면 0도로 가는 명령라인이 실행됩니다. 그러면 180도 회전이 안된 상태에서 다시 0도로 회전되어 버리는 현상이 발생합니다. 그래서 각도별 delay()함수로 시간 조정이 필요합니다.

코딩을 하면

첫번째,

#include <Servo.h> 

Servo servo1; 
int servoPin1 = 9;

void setup() 
{ 
    servo1.attach(servoPin1); 
}

void loop() 
{
    servo1.write(180);     
    delay(2000);
    servo1.write(0);     
        delay(2000);
}

두번째,

#include <Servo.h> 
 
Servo servo1; 
int servoPin1 = 9;

void setup() 
{ 
    servo1.attach(servoPin2,544,2400); //Ardunio min = 544, max=2400
}


void loop() 
{
    servo1.writeMicroseconds(2400);
    delay(2000);
    servo1.writeMicroseconds(544);
    delay(2000);   
}

5. 결과




가장 빠르게 작업했네요.

마무리


그러면 서보모터로 제어할 수 있는게 뭐가 있을까요. 지금까지 다룬 부품중에 이거랑 같이 쓸 수 있는게 뭐가 있을지 곰곰히 생각해 보세요.

가령 초음파센서를 여기에다 붙이여 어떻게 될까요. 서보모터로 각도가 제어된다면 거기에 초음파센서가 부착된다면 초음파 센서를 회전 시킬 수 있다는 의미가 됩니다. 회전 각도에 따른 거리측정이 이루어지면 어떤 일이 할 수 있을가요. 가장 많이 알려진게 레이더 입니다. 즉, 각도별 거리를 측정해서 모니터에 초음파센서에 감지된 장애물을 표시 할 수 있습니다. 또 하나는 자율주행차 입니다. 주변의 장애물을 측정해서 미로 같은 곳을 주행하면서 혼자서 피해다니면서 주행을 할 수 있게 되겠죠. 또 한가지는 180도 각도의 거리를 측정하여 그 거리들을 일정한 간격으로 게속 누적 측정한다면 그 데이터로 3D Rendering도 수행이 가능합니다. 그외로 서보모터와 초음파센서가 결합하면 다양한 표현이 가능합니다.

그러면 서보모터만으로 제어할 수 있는 다른 것들은 뭐가 있을까요. 이 글을 읽으시는 당신의 가장 가까운 곳에 정답이 있습니다. 바로 당신이 하는 행동을 비슷하게 제어할 수 있습니다. "뭘까요!" 그것은 바로 관절입니다. 관절 꺽기가 된다는 것이죠. 당신의 손을 바라보세요. 그리고 둘째(집게) 손가락을 한번 구브렸다 펴보세요. 둘째 손가락은 3마디이고 그 중간 관절을 중심으로 각 마디가 구브러졌다 펴질 꺼에요. 바로 그게 회전입니다. 그 관절 부위를 서보모터로 제어한다고 생각하시면 됩니다. 손가락 하나를 제어하게 되면 손을 제어할 수 있게 됩니다. 그러면 한쪽 팔을 제어할 수 있게 되고 그러면 로보팔을 만드는데 이용하면 되겠죠. 보다 정교하게 제어하고 싶을때 360도 회전하면서 하고 싶다면 스템모터로 제어하면 됩니다.

기본 제어로 180도 회전이였지만 좀 더 전문적으로 제어하기 위해서는 현실에서 곤충의 보행을 관찰하면서 관절의 각도를 계산해서 4,6,8축 로못으로 보행을 시킬 수 있고 사람의 손 동작의 움직일때 각 마디의 각도를 관찰하여 각도를 계산하시면 로봇팔을 만들 수 있습니다.

마지막으로 본인의 움직임의 각도를 측정해서 그걸 아두이노로 서보모터로 회전시켜 비슷하게 표현 하는 것을 상상해 보세요. 참고로 여러개의 서보모터를 아두이노에서 제어가 가능하지만 서보모터의 전류를 아두이노에서 전부 공급하면 안됩니다. 가상시뮬레이터에서는 가능하지만 현실에서는 모터에게 전류를 순간 많이 공급하면 아두이노에 불안정 전류 공급이 이루어질 수 있기 때문에 안좋습니다. 외부전류 공급을 추천 드려며 많은 모터를 제어하고자 할때는 따로 여러모터를 한번에 제어할 수 있는 보드가 있는데 오래전에 본거라 보드 이름이 생각 안나네요. 한번 구글링 하셔서 여러 모터를 제어할 수 있는 보드를 찾아보세요.


댓글()