Search

'서보모터 듀티비 각도 계산'에 해당되는 글 1건

  1. 2021.09.10 【라즈베리Pi#21】 서보(Servo) 모터 제어하기! with (파이썬 코드)
반응형

라즈베리Pi#21 서보(Servo) 모터 제어하기!  with (파이썬 코드)
RaspberryPi Servo-motor control with Python !

 안녕하세요 라즈이노 IoT 입니다.
이번 시간에는 라즈베리 Pi에서 각도단위로 매우 정확하게 움직이는 서보모터를 파이썬 코드로 제어해보는 실습입니다.
서보 모터는 다양한 곳에 활용하기 좋은 부품이기에, 이번 영상을 학습해 두면,  많은 도움이 되리라 생각됩니다.
이번 영상은 라즈베리pi에 모니터를 연결하지 않고, 윈도PC에서 원격 접속하여 진행합니다. 

만약 원격 접속 제어 방법이 궁금하다면,  라즈이노 ioT(게시글) 블로그와  유튜브 영상을 참고해 주세요.

【라즈베리Pi#19】 윈도 PC에서 라즈베리 Pi 원격 제어하기

[ 윈도 PC에서 라즈베리 Pi 원격 제어하기 - 유튜브 영상으로 보기 ]

  원격접속을 하면,  모니터 및 키보드와 마우스를 추가로 연결할 필요 없고, 멀리 떨어진 임의의 장소에 설치되었더라도, 네트워크만 연결되어 있으면, 제어할 수 있어 활용도가 높은 장점이 있습니다. 

먼저, 윈도 시작 메뉴 검색에서 ‘원격 데스크톱 연결’을 검색해서 실행합니다.

 


  라즈베리pi가 꺼져 있기에 지금은 접속이 되지 않는데요,  라즈베리pi의 전원을 넣어 부팅 시켜 볼게요. 
그리고 랜 케이블(또는 WiFi) 연결하여 네트워크에 접속할 수 있도록 합니다.
중요한 사실은 동일한(공유기) 내부 네트워크에 접속된 상태여야 원격제어가 됩니다. 
또는 외부에서 인지할 수 있는 공인 ip 주소를 할당받은 경우에  접속이 가능한데요,
만약  집에서,  같은 WiFi 공유기라 하더라도, PC(랜선) ↔ 라즈베리pi(WiFi) 연결은, 할당받는 사설 ip 대역이 달라서 접속이 안 될 수 있습니다.
그래서,   PC (LAN) ↔ 라즈베리pi (LAN)  , PC (wifi) ↔ 라즈베리pi (wifi) 연결해 주세요.
먼저, 서보모터를 아래 연결도와 실제 연결 모습을 참고하여 연결해 주세요.

※ 게시글 모든이미지는 클릭하면 확대됩니다

게시글 모든이미지는 클릭하면 확대됩니다



 회로를 연결할  때, +와 -가 합선이 되지 않도록 특별히 주의해주세요 .
합선이 되는 순간, 라즈베리pi가 큰 데미지를 먹게 되어 작동이 안 될 수 있어요.
  가급적이면,  별도의 전원을 준비해서, 아래 처럼 연결해서 사용하는 것이 합선에 대비할 수 있고 안전합니다. 

  그리고, 라즈베리파이의 GPIO핀으로는 출력 전류가 크지 않습니다(약, 50mA) ,  이런 출력을 서보모터 같은 것으로 강하게 뽑아 쓸 경우,  라즈베리파이에 손상을 입힐 수 있기 때문에, 별도의 전원을 달고 모터에 공급해주는 것이 좋습니다.   이 때,  두 전원의 GND는 서로 연결해 주어야 합니다.
 전원은, 보조 배터리나, 리튬이온, AA 건전지도 가능한데요, 약5v 정도를 구성해 주세요.
이때, 라즈베리Pi와 추가 전원의 GND(-)는 서로 연결해 주어야 합니다.  (일부 보조 배터리의 경우 잠시 배터리 사용이 없을 경우 절전 모드로 들어가버려, 전원이 꺼지는 경우가 있을 수 있습니다.  이럴 때는 , 다른 전원을 사용해 보세요)

서보모터 전용 전원을 추가한 연결도

 

그럼, 연결된 라즈베리파이를 부팅해서 네트워크까지 연결 시켜 주세요. 
그리고 처음에 한 번, 라즈베리pi에 모니터를 연결해서 할당 받는 ip 주소를 확인하여 적어두면 좋습니다.

그럼, 아래 이미지 처럼, 이렇게 확인해둔, ip를 입력하고 연결(N)을 클릭하세요.

 아래 이미지와 같은 메시지가 뜨면 예(Y)를 클릭합니다.

 

그럼, 리눅스계열 X윈도 원격 테스크톱 로그인 창이 뜹니다.

그럼,  여러분의 라즈베리파이의 삼바서버 설치 때, 유저(user)생성시 만든 user id와 비번을 입력하면 되는데요,
제 이전 영상에서는 ID와 비번은 아래와 같습니다.
username  : pi     
password  : raspberry  

로그인에 성공하면 아래와 같은 라즈베리파이의 라즈비안 OS의 화면이 열립니다.

그런데,  만약, 패스워드 비번에 문제가 없는데,  로그인이 되지 않는다면, 아래 이미지 처럼 SSH 접속 허용을 해주셔야 합니다.  (만약 SSH 허용 설정이 되지 않았다면, 라즈베리파이에 모니터를 연결하고 직접 로그인하여 설정해야 합니다)

원격접속이 되기 위해서는 사전에 SSH채널 허용함(Enabled)으로 되어 있어야 합니다

 네, 라즈베리 pi로 접속이 잘 된 것을 볼 수 있는데요, 먼저, 파이썬 코드를 작성할 텐데요, 파이썬 코드 작성은 선호하는 편집기나 혹은 메모장으로 작성해도 되는데요, 여기서는 라즈비안OS에 기본 내장된 Thonny Python IDE를 사용해 보겠습니다.
프로그램 위치는 아래 이미지를 참고해 주세요.

Thonny Python IDE 프로그램 실행 모습

먼저 서보 모터의 동작 원리에 대해 간략히 설명드릴게요.  
아래는 일반적으로 많이 사용되는 SG90 서보모터의 스팩입니다.

  서보모터는 DC 모터처럼 빠른 속도로 회전하는 용도로 사용하는 것은 아니며, 일정한 각도와 원하는 위치로 정확한 회전을 하기 위한 곳에 사용되는 모터입니다. 
예를 들어, RC-Car 앞바귀 좌우 회전, 로봇 팔다리 회전, 문 열고 닫기 등 무한 회전보다는 한정된 각도 내에서 정확한 위치제어가 필요한 곳에 많이 사용됩니다.
보다 더  정밀하고 파워를 필요로 곳에는 스텝 모터를 사용하면 되고, 서보모터는 저렴하면서 작은 크기와 낮은 소비전력으로 인해 활용성이 좋습니다. 
보통은, 90도 회전용, 180도 회전용이 주를 이루고 있으나 360도 무한 회전용도 있습니다.

서보모터는 20ms 주기의  펄스파에서 High 신호 파형을 1ms~2ms 범위를 가지고, 회전 각도가 정해지며, 180˚ 서보의 경우, 1ms 신호일 때, 0˚의 위치로 이동하며,  1.5ms 이면 90˚ ,   2ms 일 때 180˚의 위치로 이동하게 됩니다.

그래서,  1ms~2ms의 신호 범위로 0˚~180˚의 각도를 조절하게 됩니다.

단, 일부 서보모터의 경우 1~2ms 작동 범위의 오차가 다소 있으며, 180˚서보의 경우 실제적으로 움직일 수 있는 각도 범위는 2˚~177˚ 이하로 보는 것이 좋습니다.

만약 서보모터가 심하게 떨리는 증상이 있다면, 이 범위를 벗어난 신호 때문일 수 있습니다.

이미지 클릭하여 확대해서 보세요

 라즈베리pi에서 서보모터의 각도 변경은 ChangeDutyCycle (  ) 함수를 사용합니다. 
함수의 인자값으로 사용되는 듀티비는 화면과 같은 수식으로 구할 수 있습니다. 
서보모터를 0˚ 위치로 보내기 위해서는 1ms의 PWM 신호를 넣어주면 되는데요, 
- 1ms는 20ms 신호 주기의 5%에 해당됩니다.
  따라서 ‘5’%라는  인자값을 듀티비 함수에 넣어 주면, 서보모터는 0˚로 이동합니다.

서보모터를 180˚ 위치로 보내기 위해서는 2ms의 PWM 신호를 넣어주면 되는데요, 2ms는 20ms 신호 주기의 10%에 해당됩니다.  
따라서 ‘10’%라는  인자값을 듀티비 함수에 넣어 주면, 서보모터는 180˚로 이동합니다. 마찬가지로, 90˚는  인자값 7.5%를 함수에 넣으면 되고, 나머지 각도 계산도 동일한 방식입니다. 

문제는, 서보모터 제품별로 1ms~2ms(5%~10%) 작동 범위에 오차가 있을 수 있습니다.
실습에 사용된 일부 매우 저렴한 SG90 제품의 경우, 테스트를 해보니,  신호 주기를 0.6ms~2.4ms(3%~12%)의 범위로 하였을 때, 0˚~180˚의 각도 대부분을 제어할 수 있었습니다.  따라서  5%~10% 의 기본값을 적용해 보고  오차가 있을 경우, 듀티비 값을  조금씩  조절해서  각도를 최대로 안정적으로 움직이는 값을 찾아보면 됩니다.

실습 순서와 실습 파일은 화면을 참고하세요.

[ 실습 파일 링크 ] 
실습 파일 6개를 하나로 압축해 놓았습니다.

python-Code.zip
0.01MB

Thonny python IDE  편집기는 기본에 충실하고, 디버깅이 지원되며,  매우 직관적이고 사용법이 간단하여 많이 사용되고 있는 편집기입니다.  그럼, 첫 번째 실습 코드를 직접 작성하거나,  링크한 파일을 여세요. 

### (실습 1) 서보모터 각도 조절해 보기 (0도 위치로 돌리기) , 실습 파일 :  Servo1.py  ###
### 학습 자료 제공 페이지 : Rasino.tistory.com/341
# 서보는 PWM을 20ms(50hz) 주기로 동작시키고 펄스 폭(duty)만 조절해 위치(각도)를 조절함.
# 여기서 duty는 1주기 동안 High를 유지하는 기간이며, 
# 20ms 주기에 100% 면 20ms가 되는 것이고 10% 면 2ms 5% 면 1ms가 됨.
# 펄스 폭은 1ms 일때 0도 2ms 일때 180도, 중간값 1.5ms 일때 90도로 이동함.
# 단, 저렴한 서보는 3%~12%(0도~180도)의 동작 특성을 가짐.
# 만약 모터가 떨린다면, 이 범위를 벗어났기 때문이며, 0도에서 떨린다면
# 3%값에서 조금 올려주고, 180도에서 떨린다면 12%에서 값을 조금 내려주면 됨.

import RPi.GPIO as GPIO
import time

servo_pin = 18

GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin, GPIO.OUT)

pwm = GPIO.PWM(servo_pin, 50)  # 50Hz (서보모터 PWM 동작을 위한 주파수)
pwm.start(3.0)  # 0.6ms

time.sleep(2.0)
pwm.ChangeDutyCycle(0.0)

pwm.stop()
GPIO.cleanup()

준비되었으면, 코드를 실행해보세요.
실행하면, 서보의 축이 0˚의 위치로 이동하게 됩니다.
코드에 대한 설명은 주석을 상세히 달아 두었으니 꼭 참고해 보세요.
그럼, 바로 이어서 실습2번 코드를 여세요.

2번 실습은 0˚→90˚→180˚ 단계로 회전을 하되 3회 반복하도록 하였습니다.

### (실습 2-1) 서보모터 각도 조절해 보기 (0도, 90도, 180도 조절하기)  실습 파일 :  Servo2.py ###

import RPi.GPIO as GPIO
import time
servo_pin = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin, GPIO.OUT)
pwm = GPIO.PWM(servo_pin, 50)  # 50Hz (서보모터 PWM 동작을 위한 주파수)
pwm.start(3.0) #서보의 0도 위치(0.6ms)이동:값 3.0은 pwm주기인 20ms의 3%를 의미하므로,0.6ms됨.

for cnt in range(0, 3) :       # 0부터 3미만까지(3번) for문의 내용을 반복
    pwm.ChangeDutyCycle(3.0)   # 서보모터를 0도로 회전(이동)
    time.sleep(1.0)            # 서보 모터가 이동할 시간을 줌
    pwm.ChangeDutyCycle(7.5)  # 서보 모터를 90도로 회전(이동)
    time.sleep(1.0)            # 서보 모터가 이동할 시간을 줌
    pwm.ChangeDutyCycle(12.5)  # 서보 모터를 180도로 회전(이동)
    time.sleep(1.0)            # 서보 모터가 이동할 시간을 줌
    
pwm.ChangeDutyCycle(0.0)

pwm.stop()
GPIO.cleanup()

준비가 되었으면, 2번 코드를 다시 실행해 보세요.

실습 2-1 실행 모습

 

### (실습 2-2) 서보모터 각도 조절해 보기2 (0도, 45도, 90도, 135도 , 180도,...역순으로 조절하기)
조정된 듀티비 약 3%→12%를 적용하였습니다.   

import RPi.GPIO as GPIO
import time
servo_pin = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin, GPIO.OUT)
pwm = GPIO.PWM(servo_pin, 50)  # 50Hz (서보모터 PWM 동작을 위한 주파수)
pwm.start(3.0) #서보의 0도 위치(0.6ms)이동:값 3.0은 pwm주기인 20ms의 3%를 의미하므로,0.6ms됨.
timeA = 0.6

for cnt in range(0, 3) :       # 0부터 3미만까지(3번) for문의 내용을 반복
    pwm.ChangeDutyCycle(3.0)   # 서보모터를 0도로 회전(이동)
    time.sleep(timeA)            # 서보 모터가 이동할 시간을 줌
    pwm.ChangeDutyCycle(5.5)  # 서보 모터를 45도로 회전(이동)
    time.sleep(timeA)            # 서보 모터가 이동할 시간을 줌
    pwm.ChangeDutyCycle(7.5)  # 서보 모터를 90도로 회전(이동)
    time.sleep(timeA)            # 서보 모터가 이동할 시간을 줌
    pwm.ChangeDutyCycle(9.5)  # 서보 모터를 135도로 회전(이동)
    time.sleep(timeA)            # 서보 모터가 이동할 시간을 줌    
    pwm.ChangeDutyCycle(12.5)  # 서보 모터를 180도로 회전(이동)
    time.sleep(timeA)            # 서보 모터가 이동할 시간을 줌
    pwm.ChangeDutyCycle(9.5)  # 서보 모터를 135도로 회전(이동)
    time.sleep(timeA)            # 서보 모터가 이동할 시간을 줌    
    pwm.ChangeDutyCycle(7.5)  # 서보 모터를 90도로 회전(이동)
    time.sleep(timeA)            # 서보 모터가 이동할 시간을 줌
    pwm.ChangeDutyCycle(5.5)  # 서보 모터를 45도로 회전(이동)
    time.sleep(timeA)            # 서보 모터가 이동할 시간을 줌
    pwm.ChangeDutyCycle(3.0)   # 서보모터를 0도로 회전(이동)
    time.sleep(timeA)            # 서보 모터가 이동할 시간을 줌

pwm.ChangeDutyCycle(0.0)
pwm.stop()
GPIO.cleanup()

실습 2-2를 실행한 모습입니다.

 

그리고 마지막 실습 파일 Servo3-3을 여세요.
3%↔12%(0˚↔180˚)의 값을 1%단위로  왕복하도록 구성했습니다.

### (실습 3-1) 서보모터 각도 조절해 보기 (0~180도까지, 1%단위로 조절하기)
조정된 듀티비 약 3%→12% (0˚→180˚)의 값을 1%단위로 움직이도록 하였습니다. 

import RPi.GPIO as GPIO
import time

servo_pin = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin,GPIO.OUT)
pwm = GPIO.PWM(servo_pin, 50)
pwm.start(3.0)

for high_time in range (30, 125):
    pwm.ChangeDutyCycle(high_time/10.0) # for 반복문에 실수가 올 수 없으므로 /10.0 로 처리함. 
    time.sleep(0.02)
    
pwm.ChangeDutyCycle(3.0)
time.sleep(1.0)
pwm.ChangeDutyCycle(0.0)

pwm.stop()
GPIO.cleanup()

실습 3-1 실행 모습

 

### (실습 3-2) 서보모터 각도 조절해 보기 (0~>180도 까지만 1%씩 움직이기 x 3회)

 

import RPi.GPIO as GPIO
import time

servo_pin = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin,GPIO.OUT)
pwm = GPIO.PWM(servo_pin, 50)
pwm.start(3.0)

for i in range (0,3) :    
    for high_time in range (30, 125):
        pwm.ChangeDutyCycle(high_time/10.0) # for 반복문에 실수가 올 수 없으므로 /10.0 로 처리함. 
        time.sleep(0.02)
    
    pwm.ChangeDutyCycle(3.0)    
    time.sleep(1.0)
    
pwm.ChangeDutyCycle(0.0)
pwm.stop()
GPIO.cleanup()

실습 3-2 실행 모습

 

### (실습 3-3) 서보모터 각도 조절해 보기 (0↔180도 1% 단위로 왕복 움직이기 x 3회)

import RPi.GPIO as GPIO
import time

servo_pin = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin,GPIO.OUT)
pwm = GPIO.PWM(servo_pin, 50)
pwm.start(3.0)

for i in range (0,3) :    
    for high_time in range (30, 125):
        pwm.ChangeDutyCycle(high_time/10.0) # for 반복문에 실수가 올 수 없으므로 /10.0 로 처리함. 
        time.sleep(0.02)
 
    for high_time in range (124, 30,-1):
        pwm.ChangeDutyCycle(high_time/10.0) # for 반복문에 실수가 올 수 없으므로 /10.0 로 처리함. 
        time.sleep(0.02)
        
pwm.ChangeDutyCycle(0.0)
pwm.stop()
GPIO.cleanup()

실습 3-3 실행 모습

그리고, 터미널 창을 통해 명령어로 파일을 실행시켜 볼 수 있습니다.
우선, 파일 탐색창을 열어 파이썬 파일을 저장한 위치를 먼저 확인해보면 찾기 쉽습니다.
터미널 창을 열고, 리눅스 명령어를 사용하여, python 실습 파일이 저장된 위치로 이동하세요.



그리고, 아래 처럼, 파이썬 실행 명령으로 실행 시키면, 서보모터가 동작하는 것을 볼 수 있습니다.

명령어 : sudo python3  파일명
$ sudo python3  Servo3-2.py

【 설명 내용 영상으로 시청하기 】


네, 이렇게 해서 서보모터를 라즈베리pi에서 제어하기 위한 전반적인 내용을 다루었고,
파이썬 코드를 이용해서 직접 제어해 보았습니다.
감사합니다.

반응형