2 분 소요

모터문제를 해결하고 학습을 진행하자!

모터문제를 해결하다.

어제 모터문제로 애를 먹었었다. 그래서 오늘 아침에 서보모터만 뜯어서 나의 아두이노에 연결을 해보았다.

아래는 그때 사용한 코드이다.

#include <Servo.h>
Servo servo;
int value = 0;

void setup() {
  servo.attach(7);
  Serial.begin(9600);
}


void loop() {
  if(Serial.available())
  {
    char in_data;
    in_data = Serial.read();
    if(in_data == '1')
    {
      value += 30;
      if(value == 180)
      value = 0;
    }
    else
    value = 0;

    servo.write(value);
  }
}

이 코드는 Arduino와 Servo 모터를 사용하여 시리얼 통신을 통해 스티어링 모션을 제어하는 예제코드이다.

일단 setup()부분에서 아두이노의 7번핀을 통해 신호를 주도록 해주었다. 그래서 PWM세팅에 변화를 주면 이 7번핀의 전류신호가 변하게 될 것이다.

그리고 loop()부분에서 시리얼 모니터에서 입력한 값을 받아 문자형 변수in_data에 저장하고, 그 값이 문자’1’인지 판단하고 참이면 Servo모터의 위치값을 30씩 증가시킨다. 그리고 모터의 위치값이 만약 180이 되면 0으로 초기화시킨다 그리고 만약 ‘1’이 아닌 다른 문자가 수신되면 이떄도 Servo 모터의 위치값을 0으로 초기화한다. 이 코드를 아두이노에 upload하고 돌려보니 차량의 모터가 어느정도 돌아가는 것을 볼수가 있었다. 한가지 아쉬운 점은 모터가 중간에 덜덜 거린다는 것이었다. 그럴때는 같은 값을 두번 입력해줘야 문제가 해결되었다.

모터가 덜덜 떨리는 이슈는 축의 문제 때문이다!

찾아보니 서보모터에 설정된 값을 업로드 할경우, 축이 ‘덜덜덜’ 떨릴 떄가 있다고 한다. 이는 최소치의 각도와 최대치의 각도를 설정해줄때, 자주 생기는 문제라 카더라?ㄷㄷ. (물론 서보모터의 축이 플라스틱 재질이라 내구성 측면에서 취약하기 때문에, 약해서 떨리는 것도 있겠지만)이를 해결하기 위해 축이 금속으로 된 서보모터를 사용하면 이 점을 보완할수도 있고, 코드상으로 보완하기 위해서는 servo모터를 안전하게 사용하기 위해 사용하는 전용코드인 (Servo).detach()를 사용하는 방법이다.

image-20240201135535128

코드리뷰:

  1. #include <Servo.h>: Servo 라이브러리를 포하합니다.
  2. Servo servo: Servo 객체를 생성합니다
  3. void setup(): 초기 설정을 수행하는 함수입니다.
  • servo.attach(9); : Servo 모터를 7번핀에 연결
  • servo.write(90); : Servo 모터를 초기위치로 설정하기 위해 90도 회전
  • delay(1000) : 1초 동안 대기
  • servo.detach() : Servo 모터를 작동 멈춤 상태로 전환

이 코드의 목적은 단순하다. 한줄로 말하자면 “동작 끝냈어? 그러면 전원 끊어!”이거다.

아두이노가 setup()을 실행하면 Servo모터를 90도 회전시킬 것이다. 1초 대기후 detach()를 써서해당 모터를 논리적으로 때어내어 전원을 끊어낸다.

이제 이 코드를 라즈베리 파이에 녹여내기 위해 파이썬 참조코드로 변환해보았다.

파이썬 코드(라즈베리파이버전)

아두이노의 동작을 대체하기 위해 RPi.GPIO 라이브러리를 사용했다. 변환된 예제코드는 다음과 같다.

import RPi.GPIO as GPIO
import time

# GPIO 핀 번호 설정
servo_ppin = 7

# GPIO 초기화
GPIO.setmode(GPIO.BOARD)
GPIO.setup(servo_pin, GPIO.OUT)

# 서보모터 객체 생성
servo = GPIO.PWM(servo_pin, 50) # PWM 주파수 50Hz 설정

try:
	# 서보모터를 초기 위치로 설정(90도)
    servo.start(7.5) #duty cycle 값 설정(2.5%는 0도, 12.5%는 180도)
    
    # 1초 대기
    time.sleep(1)

finally:
    # 서보 모터 작동 멈춤
    servo.stop()
    GPIO.cleanup()

아두이노에서는 ‘Servo.h’ 헤더파일을 사용하여 서버모터를 제어했었는데 여기서는 서보모터든 블루투스 모듈이든 상관없이 GPIO.PWM()을 사용하게 된다.

좀 더 코드리뷰하자면, RPi.GPIO 라이브러리를 사용하여 GPIO핀을 설정하고 Servo 모터를 제어한다. PWM을 사용하여 서보 모터의 각도를 조절하고, time.sleep()함수를 이용하여 1초 동안 대기합니다. 코드 실행이 끝나면 servo.stop()GPIO.cleanup()을 사용하여 전원을 논리적으로 끊어줄 수 있겠다.

근데 나는 여기 servo.start(7.5)에서 왜 하필 7.4인가?라는 자문을 했었는데, 다음과 같은 원리가 있었다.

  • ‘7.5’는 PWM(Pulse Width Modulation)의 duty cycle을 나타낸다. Servo 모터는 펄스의 폭에 따라 움직이며, 일반적으로 이 펄스 폭이 1ms에서 2ms 사이의 값을 갖습니다. 따라서 ‘7.5’는 duty cycle이 7.5%인 펄스를 생성하는 것을 의미한다.

  • 서보모터의 각도는 펄스 폭에 따라 결정되며, 펄스의 길이가 짧을수록 모터는 한쪽으로 회전하고, 길면 다른방향으로 회전합니다. 대부분의 서보모터는 0도와 180도 사이에서 동작하며, 각도에 따라 duty cycle을 조정하여 제어한다고 한다.
  • 서보모터의 각도와 듀티 사이클간의 관계는 다음과 같다.
image-20231230154210231

댓글남기기