2015년 2월 3일 화요일

아두이노 (모터 제어)

* 무조건적으로 풀업 저항을 달고 시작할 것!!!!!
* 회로를 혼자 만들 수 있는 수준의 사람이라고 가정하고 써놓음


-서보 모터
서보는 지속적으로 회전하는 대신 어떤 위치로 이동하는 방식으로 작동되기 때문에 물리적인 이동을 정밀하게 제어하는 데 유용하다(특히 0도 ~ 180도 사이에서)

서보 모터 내부 구조

위치 피드백이 끊어져 있는 연속 회전 서보 모터를 사용하면 계속 회전할 수 있다.
                                               // 모터 쉴드를 사용하지 않아도 된다.

서보 모터는 펄스의 지속 시간에 반응한다.
펄스의 지속 시간에 따른 회전방향

-----------------------ㅣ---------------------------ㅣ------------------------>
                                             1ms                                                  2ms
    한쪽 끝으로 회전                 펄스폭에 비례해서 회전               반대쪽으로 회전



 -솔레노이드와 릴레이
솔레노이드는 전원이 공급되었을 때 선형 이동을 제공한다. 솔레노이드에는 전류가 코일을 통과할 때 생성되는 자기자에 의해 움직이는 금속 코어가 있다. 기계식 릴레이는 전기 접점을 연결하거나 끊어 주는 일종의 솔레노이드다.


-브러시드 및 브러시리스 모터


-스텝퍼 모터
스텝퍼는 제어 펄스에 반응해서 정해진 각도로 회전하는 모터다. 단계별 회전 각도는 모터에 따라 다르며, 단계당 1~2도부터 시작해서 30도 이상까지 다양하다.


 *모터를 선택할 때 가장 중요하게 고려하는 특성은 토크다. 
토크에 따라 모터의 최대 작업 용량이 결정된다. 일반적으로 토크가 높은 모터가 저토크 모터에 비해 크고 무거울 뿐만 아니라 전류도 많이 사용한다.


서보 모터 예제

#include <Servo.h>

Servo myservo;   // 서보를 제어할 서보 오브젝트를 만든다.

int angle =0;   // 서보 위치를 저장할 변수

void setup(){
  myservo.attach(9);   // 핀 9의 서보를 서보 오브젝트에 연결한다.
}

void loop(){
  for(angle =0; angle<180; angle+=1){   // 0도에서 180도로 이동한다.
    myservo.write(angle);                       // 'angle' 변수의 위치로 서보를 이동시킨다.
    delay(20);                                         // 서보 명령 간에 20ms를 기다린다.
  }
  for(angle = 180; angle >= 1; angle-=1){ // 180도에서 0도로 이동한다.
    myservo.write(angle);                         // 서보를 반대 방향으로 이동한다.
    delay(20);                                           // 서보 명령 간에 20ms를 기다린다.
  }
}

myservo.attach(pin, min, max);

min: 서보의 최소 각도(0도)에 해당하는 펄스 폭이며, 기본값은 554이다.

max: 서보의 최대 각도(180도)에 해당하는 펄스 폭이며, 기본값은 2400이다.

 2개 이하의 서보 제어하기(회전방향, 속도)
#include <Servo.h>

Servo myservo;

int potpin = 0;   //포텐셔미터를 연결하는 데 사용되는 아날로그 핀
int val;

void setup(){
  myservo.attach(9);
}

void loop(){
 val = analogRead(potpin);   // 포텐셔미터의 값을 읽는다.
 val = map(val, 0, 1023, 0, 180);
 myservo.write(val);
 delay(15);
}

연속 회전 서보의 속도 제어하기
#include <Servo.h>

Servo myservo1;
Servo myservo2;

int angle=0;

void setup(){
  myservo1.attach(9);
  myservo2.attach(10);
}
void loop(){
  for(angle=90;angle<180;angle+=1){
    myservo1.write(angle);
    myservo2.write(180-angle);
    delay(20);
  }
  for(angle=180;angle>=90;angle-=1){
    myservo1.write(angle);
    myservo2.write(180-angle);
  }
}

컴퓨터 명령으로 서보 제어하기
#include<Servo.h>

#define SERVOS 4
int servoPins[SERVOS] = {7, 8, 9, 10};   // 핀 7부터 핀 10까지 서보를 연결한다.

Servo myservo[SERVOS];

void setup(){
  Serial.begin(9600);
  for(int i=0; i < SERVOS; i++)
  myservo[i].attach(servoPins[i]);
}

void loop(){
  serviceSerial();
}

// serviceSerial 함수는 시리얼 포트를 검사한 후 수신된 데이터를 사용하여 위치를 갱신한다.
// 이 함수에서는 다음 형식의 서보 데이터를 원한다.
//
// "180a"는 서보 a에 180을 기록한다.
// "90b"는 서보 b에 90을 기록한다.
//

void serviceSerial(){
  static int pos = 0;
  
  if(Serial.available()) {
    char ch = Serial.read();
    
    if(isDigit(ch))                                                    // ch가 숫자라면:
    pos = pos*10 + ch - '0';                                  // 값을 누적시킨다.
    else if(ch >= 'a' && ch <= 'a'+SERVOS)           // ch가 서보에 해당하는 문자라면:
    myservo[ch - 'a'].write(pos);                         // 위치 배열에 위치를 저장한다.
  }
}

솔레노이드
int solenoidPin = 2;

void setup(){
  pinMode(solenoidPin, OUTPUT);
}

void loop(){
  long interval = 1000 * 60 * 60;   // 1시간
  
  digitalWrite(solenoidPin, HIGH);
  delay(1000);
  digitalWrite(solenoidPin, LOW);
  delay(interval);
}

대부분의 솔레노이드는 아두이노 핀에서 제공해주는 것보다 많은 전원이 필요하므로 트랜지스터를 사용해서 솔레노이드를 활성화하는 데 필요한 전류를 공급한다.

센서 + 진동 모터
const int motorPin = 3;
const int sensorPin = 0;
int sensorAmbient = 0;                        // 초기 밝기
const in thresholdMargin = 100;         // 진동 발생 조건에 해당하는 밝기 차이

void setup(){
  pinMode(motorPin, OUTPUT);
  sensorAmbient = analogRead(sensorPin);
}

void loop(){
  int sensorValue = analogRead(sensorPin);
  if( sensorValue > sensorAmbient + thresholdMargin){
    digitalWrite(motorPin, HIGH);
  }else{
    digitalWrite(motorPin, LOW);
  }
}

바이폴라 스텝퍼 모터 구동하기(아두이노 모터 실드가 필요하다)
#include <Stepper.h>

#define STEPS 24      //사용 중인 모터의 단계 수에 맞게 이 값을 변경한다.

Stepper stepper(STEPs, 2, 3, 4, 5);
// 스텝퍼 클래스의 인스턴스를 만들면서 모터의 단계 수와 모터를 연결할 핀을 지정한다.

int steps =0;

void setup(){
  stepper.setSpeed(30);  // 모터 속도를 30RPM으로 설정한다.
  Serial.begin(9600);
}

void loop(){
  if(Serial.available()){
    char ch = Serial.read();
    
    if(isDigit(ch)){
      steps = steps * 10 + ch - '0';
    }else if(ch =='+'){
      stepper.step(steps);
      steps = 0;
    }else if(ch == '-'){
      stepper.step(steps*-1);
      steps = 0;
    }
  }
}
   // 예를 들어 시리얼창에 3+, 7-로 입력한다.



바이폴라 스텝퍼 모터 구동하기
const int dirPin = 2;
const int stepPin = 3;

int speed = 100;   //원하는 속도(초당 단계 수)
int steps = 0;        // 단계 수

void setup(){
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  Serial.begin(9600);
}
void loop(){
  if(Serial.available()){
    char ch = Serial.read();
    
    if(isDigit(ch)){     // ch가 숫자라면?
      steps = steps * 10 + ch - '0';    // 값을 누적시킨다.
    }else if(ch == '+'){
      step(steps);
      steps = 0;
    }else if(ch == '-'){
      step(-steps);
      steps = 0;
    }else if(ch == 's'){
      speed = steps;
      Serial.print("Setting speed to ");
      Serial.println(steps);
      steps = 0;
    }
  }
}

void step(int steps){
  int stepDelay = 1000/speed;
  int stepsLeft;
  if(steps > 0){
    digitalWrite(dirPin,HIGH);
    stepsLeft = steps;
  }
  if(steps < 0){
    digitalWrite(dirPin,LOW);
    stepsLeft = -steps;
  }
  while(stepsLeft > 0){
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(1);
    digitalWrite(stepPin, LOW);
    delay(stepDelay);
    stepsLeft--;
  }
}



댓글 없음:

댓글 쓰기