[Raspberry Pi] - rc카 만들기 #3 ESC 제어






#3 ESC 제어




E042A 40A ESC

  • 전자변속기(ESC)
RC기기들의 브러시리스(Brushless) 모터 혹은 브러시(Brushed) 모터를 작동 시키는 것에 있어 핵심적인 부품이다.
여기서 ESC는 키보드 위의 그 esc가 아니라 Electronic Speed Controller의 이니셜이다.




RC카를 접해본 사람들이라면 ESC와 트렌스미터 간 캘리브레이션(Calibration)이 필요하다는 것을 알것이다. 전자변속기는 모터에 PWM(pulse width modulation)신호에 따라 출력을 하는데 동일한 시간축에서 펄스폭이 넓을수록 모터는 더 큰 출력을 얻게된다.
여기서 필요한 작업이 캘리브레이션이다.

캘리브레이션이란 쉽게 말해 ESC가 Raspberry Pi로 부터 받은 값에서 얼마 만큼의 출력을 내야할지 알려주는 것으로 ESC통해 모터를 제어하기 위해 필수적인 작업이다.

ESC에는 기본적으로 모터에 연결되는 2선(브러시드) 혹은 3선(브러시리스), 전원 단자(사진 deans), 스위치, 컨트롤러 선을 포함한 BEC단자가 있다.
위 사진속 제품 가장 오른쪽에 검정(Ground), 적색(6V), 흰색(Signal) 단자가있다. BEC출력이 6V로 Raspberry Pi의 전원으로 사용하기에 안전하지 않다.



SERVO가 4pin(적색) 6pin(갈색) 7pin(황색)을 사용중이다.
ESC는 9pin(검정색) 11pin(흰색)을 사용할 것이다.
저번에는 lxterminal을 열서서 스크립트를 실행전에 pigpio daemon을 따로 실행해야했다. 
아래 처럼 프로그램 상단에 추가해주면 따로 실행 할 필요가 없다.
사전에 실행하고 싶은 다른 데몬이나 스크립트가 있다면, 
call("실행할 프로그램",shell=True) 이런식으로 추가해주면 된다.
경우에 따라선 프로그램의 경로까지 명시해주어야 할 수도 있다.

  • 캘리브레이션(Calibration)
매번 연결을 할때 Dual Shock로 캘리브레이션(Calibration)을 하는 것은 상당히 번거롭기 때문에 루프에 들어가기전에 프로그램상에서 진행되도록 할 것이다.

1) 우선 ESC에 전원을 넣는다.
2) 짧은 비프음이 종류에 따라서 한번에서 세번 정도 울린다.
3) 파이썬 스크립트를 실행 시킨다.
4) 캘리브레이션(Calibration)에 성공하면 긴 비프음이 울린다.




본인이 사용한 ESC에 따라서 다를 수 있지만 여기서 사용한 ESC는 이렇게 최소값 최대값을 두번 정도 신호를 주어야 완료가 되었다.


  • 브러시 모터 제어
브러시 모터라 하면 어릴적에 가지고 놀던 일반적인 DC모터이다.
여기까지 왔다면 모터의 제어는 어렵지 않다. 서보모터를 제어했던 것처럼 하면된다.

<SERVO>
if   최소값보다 작을때 최소값으로 고정
elif 최대값보다 클때 최대값으로 고정
if   Dual Shock로부터 받은 값만큼 움직인다

<ESC_MOTOR>
-0.1 ~ 0.1 의 Dual Shock 입력값에서는 작동하지 않도록 하였다.
원치않는 움직임을 막기위한 방법이다.
마지막으로 else: 에서 ESC_POWER에 0을 주지 않고 PWM의 최대 최소의 중간 값을 준다거나 초기화 하지 않는다면 급정지로 인한 장비손상이나 원치 않는 움직임을 감상 할 수 있다.

스크립트에 pygame.time.Clock() 함수를 이용해 fps를 20으로 제한 했는데 만일 이 작업을 해주지 않으면 CPU가 매우 뜨거워지는 것을 느낄 수 있다.
CPU 온도는 lxterminal 에 vcgencmd measure_temp 로 확인 할 수 있다




#테스트 영상




  • 전체 소스코드
"""
01/24/2017 code by Heejoong
"""
#!/usr/bin/env python3
from subprocess import call
call("sudo pigpiod", shell=True)
import time
import pigpio
import pygame
import RPi.GPIO as GPIO
import math
pi = pigpio.pi()
GPIO.setmode(GPIO.BOARD)
SERVO = 4
ESC_GPIO = 17
BLACK    = (   0,   0,   0)
WHITE    = ( 255255255)
pygame.init()
#Loop until the user clicks the close button.
done = False
# Initialize the joysticks
pygame.joystick.init()
print("PiCar Online")
# -------- Main Program Loop -----------
while done==False:
    
    # EVENT PROCESSING STEP
    for event in pygame.event.get(): # User did something
        if event.type == pygame.QUIT: # If user clicked close
            done=True # Flag that we are done so we exit this loop
        # Possible joystick actions: JOYAXISMOTION JOYBALLMOTION JOYBUTTONDOWN JOYBUTTONUP JOYHATMOTION
        if event.type == pygame.JOYBUTTONDOWN:
            if joystick.get_button(0):
                print("square pressed")
            elif joystick.get_button(1):
                print("cross pressed")
            elif joystick.get_button(2):
                print("circle pressed")
            elif joystick.get_button(3):
                print("triangle pressed")
            elif joystick.get_button(4):
                print("L1 pressed")
            elif joystick.get_button(5):
                print("R1 pressed")
            elif joystick.get_button(6):
                print("L2 pressed")
            elif joystick.get_button(7):
                print("R2 pressed")
            elif joystick.get_button(8):
                print("SHARE pressed")
            elif joystick.get_button(9):
                print("OPTIONS pressed")
            elif joystick.get_button(10):
                print("left Axis pressed")
            elif joystick.get_button(11):
                print("right Axis pressed")
            elif joystick.get_button(12):
                print("PS pressed")
            elif joystick.get_button(13):
                print("Touch pad pressed")
        
    # Get count of joysticks
    joystick_count = pygame.joystick.get_count()
    # For each joystick:
    for i in range(joystick_count):
        joystick = pygame.joystick.Joystick(i)
        joystick.init()
        # SERVO MOTOR
        MAX = 1725
        MID = 1425
        MIN = 1125
        #print(joystick.get_axis(2))
        position = ((-joystick.get_axis(2))*300+MID)
        if position < MIN:
            position = MIN
        elif position > MAX:
            position = MAX
        if MIN <= position <= MAX:
            #print(position)
             pi.set_servo_pulsewidth(SERVO, position)
            #call("echo 1="+str(position)+" > /dev/servoblaster", shell=True)
        # SERVO MOTOR END
        # MOTOR Control
        power = (-joystick.get_axis(1))*50
        
        if joystick.get_axis(1)< -0.1:
            ESC_POWER  = 1520+power
            pi.set_servo_pulsewidth(ESC_GPIO, ESC_POWER)
        elif joystick.get_axis(1)> 0.1:
            ESC_POWER = 1340+power
            pi.set_servo_pulsewidth(ESC_GPIO, ESC_POWER)
        else:
            pi.set_servo_pulsewidth(ESC_GPIO, 0)
        #MOTOR End
# Close the window and quit.
# If you forget this line, the program will 'hang'
# on exit if running from IDLE.
pygame.quit ()
GPIO.cleanup()
cs



Thx.

Comments

Popular posts from this blog

[POE] - 패스 오브 엑자일 획득키 F 의 사용법 (Path of Exile)

[Arduino] - HC-06를 이용해 PC 와 Arduino 블루투스 연결

[XBOX] - 엑스박스원s 패드 and 블루투스 자동연결 for PC

[Raspberry Pi] - rc카 만들기 #2 Servo Motor