개발

Pololu - Tic Stepper Moto Controller (스텝모터 컨트롤러)

Hugh Q Lee 2022. 4. 29. 23:07

https://www.pololu.com/category/212/tic-stepper-motor-controllers

 

Pololu - Tic Stepper Motor Controllers

The Tic offers simple control of bipolar stepper motors directly from a variety of interfaces, including USB, TTL serial, I²C, hobby radio control (RC), analog voltage (potentiometer), and quadrature encoder signals.

www.pololu.com

링크 먼저 던지고 시작.

워낙 다양한 인터페이스-연결(USB, TTL serial, I2C, RC 등)을 제공하는 컨트롤러라서 쓰임이 다양하겠지만,

나의 경우는 

  1. 이 컨트롤러 보드에 micro-B usb 타입 케이블로 PC와 연결하고,
  2. 스텝 모터 연결하고(모터 드라이버 역할),
  3. 전원을 연결해서
  4. 파이썬 코딩(정확히는 코딩한 GUI 프로그램)으로 이 모터를 제어한다.

아두이노 같은 거 없이, usb연결을 통해 PC로 제어할 수 있는게 정말 좋다!

 

더보기

https://youtu.be/-cAjdT6QN_w

튜토리얼 영상 (연결 및 세팅에 대해서 친절히 설명해준다, 영어로.)

 

 

https://www.pololu.com/product/3140/resources

 

Pololu - Tic 36v4 USB Multi-Interface High-Power Stepper Motor Controller (Connectors Soldered)

The Tic 36v4 USB Multi-Interface High-Power Stepper Motor Controller makes basic control of a stepper motor easy, with quick configuration over USB using our free software. The controller supports six control interfaces: USB, TTL serial, I²C, analog volta

www.pololu.com

 

위 링크에서 운영체제(OS)에 맞춰 소프트웨어를 다운로드 받아 설치하자. 그러면 터미널에서 ticcmd를 사용할 수 있게 된다. (물론 GUI프로그램도 쓸 수 있다.)

# Uses ticcmd to send and receive data from the Tic over USB.
# Works with either Python 2 or Python 3.
#
# NOTE: The Tic's control mode must be "Serial / I2C / USB".
 
import subprocess
import yaml
 
def ticcmd(*args):
	# 이 함수로 터미널에서 ticcmd를 파이썬 코드로 실행할 수 있다.
  return subprocess.check_output(['ticcmd'] + list(args))
 
status = yaml.load(ticcmd('-s', '--full'), loader=yaml.FullLoader)
# PyYAML의 최신 버전(==6.0)에서 loader args가 필수다. 안쓰면 아래 메세지의 에러난다.
# TypeError: load() missing 1 required positional argument: 'Loader
 
position = status['Current position']
print("Current position is {}.".format(position))
 
new_target = -200 if position > 0 else 200
print("Setting target position to {}.".format(new_target))
ticcmd('--exit-safe-start', '--position', str(new_target))

시행착오를 조금 거쳤는데,

  1. 처음에는 5V 전원을 연결했는데 전압(Voltage)가 부족한 모양이었다. 작은 모터는 잘 돌렸지만, 큰 모터는 진동하지만 회전하지 않았다. 이후 12v 혹은 24v로 넉넉히 돌리는 게 내 정신 건강에 좋았다.
  2. ticcmd 이용하는 코드말고 serial을 이용하는 코드도 있었는데, 여러 스트레스를 받아서 포기했다. (코드는 아래 첨부)
더보기
# Uses the pySerial library to send and receive data from a Tic.
#
# NOTE: The Tic's control mode must be "Serial / I2C / USB".
# NOTE: You will need to change the "port_name =" line below to specify the
#   right serial port.
 
import serial
 
class TicSerial(object):
  def __init__(self, port, device_number=None):
    self.port = port
    self.device_number = device_number
 
  def send_command(self, cmd, *data_bytes):
    if self.device_number == None:
      header = [cmd]  # Compact protocol
    else:
      header = [0xAA, device_number, cmd & 0x7F]  # Pololu protocol
    self.port.write(bytes(header + list(data_bytes)))
 
  # Sends the "Exit safe start" command.
  def exit_safe_start(self):
    self.send_command(0x83)
 
  # Sets the target position.
  #
  # For more information about what this command does, see the
  # "Set target position" command in the "Command reference" section of the
  # Tic user's guide.
  def set_target_position(self, target):
    self.send_command(0xE0,
     ((target >>  7) & 1) | ((target >> 14) & 2) |
     ((target >> 21) & 4) | ((target >> 28) & 8),
     target >> 0 & 0x7F,
     target >> 8 & 0x7F,
     target >> 16 & 0x7F,
     target >> 24 & 0x7F)
 
  # Gets one or more variables from the Tic.
  def get_variables(self, offset, length):
    self.send_command(0xA1, offset, length)
    result = self.port.read(length)
    if len(result) != length:
      raise RuntimeError("Expected to read {} bytes, got {}."
        .format(length, len(result)))
    return bytearray(result)
 
  # Gets the "Current position" variable from the Tic.
  def get_current_position(self):
    b = self.get_variables(0x22, 4)
    position = b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24)
    if position >= (1 << 31):
      position -= (1 << 32)
    return position
 
# Choose the serial port name.
port_name = "COM1" # 윈도우라서 COM1로 수정했다. ## 여기가 문제였다.
 
# Choose the baud rate (bits per second).  This must match the baud rate in
# the Tic's serial settings.
baud_rate = 9600 # 세팅에 맞춰 진행
 
# Change this to a number between 0 and 127 that matches the device number of
# your Tic if there are multiple serial devices on the line and you want to
# use the Pololu Protocol.
device_number = 13 # 이것도 소프트웨어에서 세팅에 맞춰 진행했다.
 
port = serial.Serial(port_name, baud_rate, timeout=0.1, write_timeout=0.1)
 
tic = TicSerial(port, device_number)
 
position = tic.get_current_position()
print("Current position is {}.".format(position))
 
new_target = -200 if position > 0 else 200
print("Setting target position to {}.".format(new_target));
tic.exit_safe_start()
tic.set_target_position(new_target)

이때 얻은 에러메세지는 아래와 같은데, 해결하지 못했다. 시리얼 통신에서 문제가 있어서 정보를 못 받아오는 듯 하다.

RuntimeError: Expected to read 4 bytes, got 0.

<수정: 2022.05.05.>

port_name을 'COM1'으로 줬었는데, 이게 아니다. Serial코드는 Serial 포트로 통신할 때만 사용이 가능하다고 한다. USB 연결로는 시리얼 포트로 연결이 안되기 때문에 컨버터 사용해서 PC에 연결하라고 하는데... 문제는 내 PC에 시리얼 포트가 없다 ㅡㅡ;;

해서 이 코드 사용은 포기한다. ㅠㅠ 

728x90