파이썬 아두이노 서보모터 제어 - paisseon adu-ino seobomoteo jeeo

CodingMaker

Python

Python에서 아두이노 서보 모터 움직이기

메이커K 2018. 5. 8. 11:24

먼저 아두이노에 쉴드를 연결한 후, 아래 사진과 같이 서보모터 2개를 각각 쉴드에 연결한다.

신호의 노란 선이 각각 D8과 D7에 연결한다.

파이썬 아두이노 서보모터 제어 - paisseon adu-ino seobomoteo jeeo

파이썬

import serial

arduino = serial.Serial('COM12',9600)

while(1):

    c=input()

    if c =='q':

        break

    else:

        c=c.encode('utf-8')

        arduino.write(c)

파이썬에서 위의 코드를 입력한다. COM12에 아두이노가 연결되어 있기 때문에 COM12로 입력한다. 스케치에서 확인한다.

입력이 끝나면 Ctrl+F5 키를 누른다음 아래 창이 뜨면,

1~4중 하나의 값을 입력하면 서보모터의 각도가 5도씩 움직인다.

아두이노

#include <Servo.h>

Servo myservoH;  // create servo object to control a servo

Servo myservoV;

int posH = 90;

int posV = 90;

void setup() {

  myservoH.attach(8);  // 서보모터를 쉴드의 8번에 연결한다.

  myservoV.attach(7);  // 서보모터를 쉴드의 7번에 연결한다.

  Serial.begin(9600);

}

void loop() {

  while (Serial.available() > 0) {

    long value = Serial.parseInt();

    int backUpH = posH;

    int backUpV = posV;

    switch (value) {

      case 1:

        //posH = posH - 5; 같은 표현이다 posH -= 5;

        posH -= 5;

        break;

      case 2:

        posH += 5;

        break;

      case 3:

        posV -= 5;

        break;

      case 4:

        posV += 5;

        break;

    }

    if (posH<0 || posH>180) {

      posH=backUpH;

    }

    if (posV<0 || posV>180) {

      posV=backUpV;

    }

    myservoH.write(posH);

    myservoV.write(posV);

  }

파이썬

import cv2

import serial

arduino = serial.Serial('COM12',9600)

cap = cv2.VideoCapture(0)  

while(True):  

    # Capture frame-by-frame  

    ret, frame = cap.read()  

    cv2.imshow('frame',frame)

    key = cv2.waitKey(1) & 0xFF

    if key == ord('q'):  

        break

    elif key ==ord('a'):          #왼쪽

        arduino.write(b'1\n')

        print(b'1\n')

    elif key ==ord('d'):          #오른쪽

        arduino.write(b'2\n')

        print(b'2\n')

    elif key ==ord('w'):          #위

        arduino.write(b'3\n')

        print(b'3\n')

    elif key ==ord('s'):          #아래

        arduino.write(b'4\n')

        print(b'4\n')

# When everything done, release the capture  

cap.release()  

cv2.destroyAllWindows()  

frame이라는 이름의 비디오 화면이 나타나며 키보드의 a 와 d로 오른쪽 왼쪽으로 서보모터를 이동시키고 키보드의 w와 s로 위 아래로 서보모터를 이동시킨다.

라즈베리파이 같이 파이썬으로 제어 가능한 장치가 있을때 서보모터를 제어하는 기초적인 방법이다.


1. 회로도

서보모터의 경우 아래와 같이 연결시켜주면 된다.

  • VCC => 빨강
  • GND => 검정 or 갈색
  • 신호선 => 노랑 or 주황

파이썬 아두이노 서보모터 제어 - paisseon adu-ino seobomoteo jeeo


2. 파이썬 코드

pwm.ChangeDutyCycle 인자에다가 값을 변경해주면 서보모터가 해당 위치로 변경되며, 이후에는 반드시 time.sleep 값을 넣어주어야 작동이 된다.

pwm.ChangeDutyCycle 의 인자로, 서보모터는 보통 2~12사이에서 (0%~100%)를 이동할 수 있는 값을 가지며, 서보모터마다 값이 조금씩 다르기에 직접 파이썬 쉘을 이용해서 값을 넣어주면서 최대 최소값을 알아내면 되고, 이에 따라 각도로 조절을 하고 싶을때는 변환식을 만드는 등, 코드를 변경해서 쓰면된다.

import RPi.GPIO as GPIO # 라즈베리파이 GPIO 핀을 쓰기위해 임포트
import time # 시간 간격으로 제어하기 위해 임포트

def servoMotor(pin, degree, t):
    GPIO.setmode(GPIO.BOARD) # 핀의 번호를 보드 기준으로 설정, BCM은 GPIO 번호로 호출함
    GPIO.setup(pin, GPIO.OUT) # GPIO 통신할 핀 설정
    pwm=GPIO.PWM(pin, 50) # 서보모터는 PWM을 이용해야됨. 16번핀을 50Hz 주기로 설정

    pwm.start(3) # 초기 시작값, 반드시 입력해야됨
    time.sleep(t) # 초기 시작값으로 이동하고 싶지 않으면 이 라인을 삭제하면 된다.
    
    pwm.ChangeDutyCycle(4) # 보통 2~12 사이의 값을 입력하면됨
    time.sleep(t) # 서보모터가 이동할만큼의 충분한 시간을 입력. 너무 작은 값을 입력하면 이동하다가 멈춤

    # 아래 두줄로 깨끗하게 정리해줘야 다음번 실행할때 런타임 에러가 안남
    pwm.stop() 
    GPIO.cleanup(pin)

servoMotor(16, 8, 1) # 신호선을 16번 핀에 연결, 8의 각도로 1초동안 실행


참고 자료

  • https://www.youtube.com/watch?v=SGwhx1MYXUs