본문 바로가기
로봇 이야기/controller

PCA9685 서보모터 드라이버

by 노땅엔진니어 2022. 12. 12.

1. 들어가기 전에

한 두개의 서보모터 제어는 MCU(MicroController Unit)의 PWM(Pulse Width Modulation)으로 합니다. 로봇을 제작할 때 여러 개의 서보모터를 제어해야 하는 경우 별도의 서보모터 드라이버가 필요 합니다.  취미로  로봇 제작을 하는 경우 아두이노 용으로 출시 된 "Adafruit 16-Channel 12-bit PWM/Servo Driver - I2C interface - PCA9685" 제품을 사용합니다. 국내에서 Adafruit사의 제품은 구하기 힘들고 대부분 짝퉁 제품을 구할 수 있습니다. 짝퉁 제품은 Adafruit사의 회로도와 완전히 동일하지 않지만 거의 유사하기 때문에 큰 문제 없이 사용할 수 있습니다.

PWM : https://duvallee.tistory.com/6

I2C-BUS : https://duvallee.tistory.com/4

I2C-BUS 활용 : https://duvallee.tistory.com/5

1.1 Adafruit PCA9685 Board

그림-1. 은 PCA9685보드 사진입니다. 납땜이 필요하지만 PCA9685는 I2C 주소를 변경할 수 있어, 하나의 I2C-BUS에 여러 개의 PCA9685 보드를 사용하여 16개 이상의 서보모터를 제어 할 수 있습니다.

PCA9685 I2C 기본 주소(7비트 주소) : 1000 000b (1A5A4A3 A2A1A0)

MCU와는 4선(GND, SCL, SDA, VCC)을 연결 합니다. VCC는 PCA9685칩의 VCC로써 MCU와 같은 전압을 사용해야 합니다. 예를 들어 아두이노의 경우에는 아두이노의 VDD가 +5V이기 때문에 PCA9685의 VCC에 +5V를 연결하면 I2C(SCL, SDA) 통신은 5V로 합니다.

VCC 전원 (PCA9685 VDD)

STM32 MCU를 포함한 대부분의 MCU는 VDD가 +3.3V이기 때문에 PCA9685의 VCC에는 +3.3V를 공급해야 합니다.  만약 +3.3V MCU에 PCA9685의 VCC에 +5V를 공급하게 되면 정품 Adafruit사의 보드는 내부 SCL과 SDA가 VCC(이 경우 5V) 풀업(pull-up)으로 인하여 MCU의 SCL과 SDA 라인에 5V가 인가되어 MCU가 망가 집니다. 다만, 몇몇 MCU는 SCL과 SDA 라인에 5V 입력을 허용하는 경우가 있어, 그런 MCU의 경우에는 정상적으로 사용 가능 합니다.(STM32 MCU의 경우 FT(5V tolerant I/O) 핀 일때)
몇몇 짝퉁 PCA9685 보드는 SCL과 SDA에 5V 풀업이 걸려 있지 않고 이론적으로는 하이(HIGH,  최소 범위 : VDD(5V)*0.7= 3.5V)의 최소 전압 3.5V보다 낮은 3.3V이기 때문에 통신이 되지 않아야 하나 통신이 되는 것을 확인 할 수 있습니다. 통신이 된다고 해서 정상 동작을 한다는 보장은 아닙니다.

V+ 전원 (서보모터 전원)

V+전원은 PCA9685과는 연결되어 있지 않고 서보모터에 공급되는 전원 입니다. 그러므로 MCU 보드의 +5V와 연결하지 않는 것이 좋습니다. MCU 보드의 경우에 MCU가 사용할 허용 전류에 맞게 설계되었기 때문에 보통 서보모터 한개만 해도 허용 전류를 초과하기 때문에 서보모터가 동작하는 순간 MCU 보드에서 전류가 부족하여 MCU가 다운되거나 리부트 될 수 있습니다.
보통 V+ 전원은 별도로 구성을 하거나 배터리나 아답터에서 직접 공급을 합니다.

2. PCA9685

그림-2는 PCA9685의 블럭다이어그램 입니다. 블럭다이어그램을 통해서 PCA9685가 어떻게 동작을 하는지 알아 봅니다.

PCA9685는 크게 I2C-BUS CONTROLLER와 클럭(clock), 먹스(MUX), 레지스터(register) 블럭으로 나눌 수 있습니다.

2.1. I2C-BUS CONTROLLER

I2C-BUS CONTROLLER 블럭은 외부 MCU와 통신을 담당 합니다. PCA9685는 I2C 슬레이브(slave)로 동작을 하며, 블럭 다이어그램의 SCL은 입력만 받고 SDA는 양방향 통신을 합니다. SDA에 모스펫(MOSFET)은 출력을 담당하고 INPUT FILTER는 입력을 담당 합니다. PCA9685는 VDD에 전원이 공급되면 POWER-ON RESET에 의해 리셋이 되고 외부 A0~A5의 핀 상태를 읽어 I2C 슬레이브 주소를 결정 합니다.
I2C-BUS CONTROLLER는 MCU로 부터 레지스터에 데이터를 받으면 내부 레지스터(register)에 데이터를 쓰거나 읽습니다.

2.2. 먹스(mux)

먹스는 여러 개의 입력선 중에 하나를 선택하여 단일 출력을 합니다. PCA9685의 먹스(mux)의 출력을 선택하는 입력은 다음과 같습니다.

  • 외부 nOE 핀
  • 16채널을 동시에 제어하는 레지스터
  • 채널별 제어하는 레지스터

먹스의 출력단에는 모스펫(MOSFET)을 통해서 PWM 신호를 출력 합니다. 출력에는 2가지로 지원을 합니다. 첫 번째는 오픈 드레인(open drain)이고 두 번째는 토템폴(totem pole) 입니다.

왼쪽 그림은 오픈 드레인을 설명하고 있습니다. 그림과 같이 입력이 하이(HIGH)일 때는 출력이 로우(LOW)이나 입력이 로우이면 출력은 알 수 없는 상태 입니다. 그러므로 출력을 하이 만들기 위해 PCA9685 외부에 풀업(pull-up)을 반드시 추가해야 합니다.
오픈 드레인의 장점은 PCA9685의 VDD가 5V일 때 PWM의 진폭도 5V가 됩니다.
만약 PWM 신호로 제어하는 서보모터의 PWM 진폭이 7.2V라고 가정을 하면, PCA9685를 통해서는 해당 서보모터를 제대로 제어를 할 수 없습니다. 이런 경우 출력을 오픈 드레인으로 설정하고 외부 풀업에 7.2V를 걸어 놓으면 PWM 진폭은 7.2V가 되어 서보모터를 제어할 수 있습니다.
반대로 서보모터의 PWM 진폭이 2V라면 PWM의 5V 진폭을 주었을 때 서보모터의 내부 회로가 망가 질 수도 있습니다. PCA9685의 VCC와 서보모터에서 요구하는 PWM의 진폭가 차이가 있을 때 오픈 드레인으로 해결할 수 있습니다.

대부분의 PWM 출력 핀은 그림-4와 같이 푸시-풀로 구성을 합니다. 푸시-풀은 N채널 모스펫(MOSFET)과 P채널 모스펫(MOSFET)을 갖고 입력이 로우이면 출력은 하이(VDD)이고 입력이 하이(1)이면 출력은 로우(0)가 됩니다.
PCA9685의 PWM 출력 핀은 푸시-풀이 아닌 아래와 같이 토템-폴로 구성되는데 푸시-풀과 같이출력은 로우(0과 하이(VDD)와 같이 유사 합니다.

PCA9685의 PWM 출력을 토템-폴로 설정하면 PWM의 진폭은 PCA9685의 VDD가 됩니다. Adfruit PCA9685 보드의 경우에는 오픈 드레인(open drain)을 위한 회로 구성이 없기 때문에 토템-폴로만 출력을 할 수 있습니다.

 

 

 

 

2.3. 클럭(Clock)

클럭은 PWM 신로를 만드는데 매우 중요 합니다. 정확한 PWM의 주파수(frequency)와 듀티 사이클을 만들기 위해서는 클럭 및 타이머에 대해 이해를 해야 합니다.

PCA9685는 클럭을 외부에서 입력 받거나 내부의 25 MHz 오실레이터(oscillator)를 사용 합니다. 외부 클럭은 최대 50 MHz까지 입력을 받을 수 있으나 우리가 쉽게 구할 수 있는 Adafruit나 짝퉁 보드에는 외부 클럭이 없기 때문에 내부 클럭을 사용 합니다.

프리스케일(PRESCALE)과 PWM 주파수(주기, frequency)

보통 입력 받은 클럭을 갖고 바로 타이머를 사용하지 않습니다. 프리스케일(PRESCALE)을 통해 분주된 클럭을 만들어서 사용을 합니다. 얼마로 분주 할 것인가는 PWM의 주파수(frequency)에 따라 결정 됩니다.
그림-6은 입력 클럭을 분주하여 12-비트 카운터가 어떻게 카운팅을 하는지 보여주는 그림 입니다. 분주 클럭의 한 주기(한 클럭)마다 카운터는 0부터 4095까지(4096개) 증가를 한 후에 0으로 리셋 된 후에 다시 카운팅을 합니다.

PCA9685의 지원하는 PWM 주파수 범위는 다음과 같습니다. (만약 제어가 필요한 장치의 PWM 주파수가 아래 범위 값을 넘는다면 PCA9685는 사용할 수 없습니다.)

  • 24 Hz ~ 1526 Hz

제어하고자 하는 서보모터의 지원하는 PWM 주파수를 통해서 프리스케일 값을 아래 공식으로 계산 합니다. (osc_clock은 내부 클럭을 사용하므로 25 MHz 입니다.)

PWM 주파수는 사용하고자 하는 서보모터 데이터시트를 참조하여 알 수 있으나 아두이노용이나 알리에서 판매를 하는 취미용 서보모터의 경우 데이터시트가 없고 판매 사이트에서도 불분명하게 표현을 합니다. 알리에서 판매하는 대부분의 PWM 주파수(working frequency) 범위는 다음과 같습니다.

  • 50 Hz ~ 350 Hz (추천 PWM 주파수는 330 Hz 입니다.)

아두이노에서 많이 사용하는 MG996R의 PWM 주파수는 다음과 같습니다.

  • 50 Hz

취미로 구하는 서보모터는 워낙 짝퉁도 많고, 제대로 PWM 주파수 범위를 알려주지 않습니다. 가장 많이 처음 시도하는 주파수는 200 Hz에서 시작을 합니다.

PWM 듀티 싸이클(duty cycle)타이머와 LED ON/OFF

그림-6은 클럭(내부 클럭 25 MHz)을 프리스케일(prescale + 1) 값으로 분주 된 클럭에 12비트 카운터가 0부터 4095까지 카운팅 됩니다. 4096이 되는 순간 카운터는 리셋되고 0부터 다시 시작 합니다.

PCA9685는 LED ON과 LED OFF 레지스터에 0 ~ 4095 사이의 카운터 값을 설정하면 설정한 레지스터 값과 카운터가 같은 값일 때 동작 됩니다. 그러므로 LED ON과 LED OFF 레지스터에 같은 값을 설정하지 않습니다. (아래 예는 LED_ON 레지스터에 320, LEF_OFF 레지스터에 1200을 설정 했습니다.)

LED 백라이트(backlight) 제어는 PWM의 듀티 싸이클의 퍼센트로 제어를 합니다. 10% 듀티 사이클은 4096의 10%인 409 클럭을 하이로 유지하면 밝기는 10%가 됩니다. 그러나 서보모터 제어는 듀티 사이클의 퍼센트가 아닌 시간으로 위치를 제어 합니다. 알리에서 판매되는 취미용 서보모터의 규격은 다음과같습니다.

  • PWM 주파수 : 50 ~ 330 Hz (330 Hz 추천)
  • 180도 (500 ~ 2500 us, 중앙(center 90도 : 1500 us)
  • dead zone : 3 ~ 6 us

아두이노에서 많이 사용하는 MG996R, SG90 서보모터는 다음과 같습니다.

  • PWM 주파수 : 50 Hz
  • 180도 (1000 ~ 2000 us, 중앙(center 90도 : 1500 us)
  • dead zone : 5 us

dead zone이 5 us라면 서보모터 위치가 1500 us(중앙)에 있을 때 1496 ~ 1504 us 사이의 값으로 PWM 듀티를 변경하면 서보모터의 위치를 변경되지 않고 5 us 이상 듀티 값을 변경해야 원하는 위치로 이동을 합니다.

 

서보모터를 정확하게 제어를 하기 위해서는 12비트 카운터의 한개 카운터의 시간을 구해야 합니다. 한개의 카운터는 클럭을 프리스케일 + 1 값으로 분주된 클럭을 1초로 나누면 1 카운터의 시간을 알 수 있습니다.

  • PWM 주기 200 Hz 일 때 1 카운터의 시간 : 1.24 us
  • PWM 한 주기(4096개의 카운터)의 시간 : 5.079 ms

위 시간을 갖고 서보모터의 위치를 중앙(center 90도)에 위치 시키기 위해서는 약 1210 카운터(약 1500 us) 동안 하이(HIGH)를 유지하면 됩니다. 예를 들면 다음과 같습니다.

  • LED ON : 0, LED OFF : 1209
  • LED ON : 100, LED OFF : 1309

카운터의 시작은 중요하지 않습니다. LED_OFF - LED_ON + 1 의 값이 1210이 되면 됩니다.(다만, LED OFF 값이 4095를 넘으면 안됩니다.)

2.4. 레지스터(register)

PCA9685는 총 76개의 레지스터를 갖고 있으며, 레지스터에 대한 내용은 다음 장에서 상세히 설명 합니다.

3. 소프트웨어(디바이스 드라이버)

3.1. 레지스터(register)

다음은 PCA9685의 레지스터 입니다.

Mode register 1 (ADDR : 0x00, MODE1)

BIT [7] RESTART
    0 : Restart disabled.
    1 : Restart enabled.
BIT [6] EXTCLK
    0 : Use internal clock.(25 MHz)
    1 : Use EXTCLK pin clock
BIT [5] AI
    0 : Register Auto-Increment disabled.
    1 : Register Auto-Increment enabled.
BIT [4] SLEEP
    0 : Normal mode.
    1 : Low power mode. Oscillator off.
BIT [3] SUB1
    0 : PCA9685 does not respond to I2C-bus subaddress 1.
    1 : PCA9685 responds to I2C-bus subaddress 1.
BIT [2] SUB2
    0 : PCA9685 does not respond to I2C-bus subaddress 2.
    1 : PCA9685 responds to I2C-bus subaddress 2.
BIT [1] SUB3
    0 : PCA9685 does not respond to I2C-bus subaddress 3.
    1 : PCA9685 responds to I2C-bus subaddress 3.
BIT[0] ALLCALL
    0 : PCA9685 does not respond to LED All Call I2C-bus address.
    1 : PCA9685 responds to LED All Call I2C-bus address.

 

MODE1 레지스터에서 중요한 비트는 BIT[6], BIT[5], BIT[4]가 중요 합니다. 이 중에 BIT[5]는 보통 I2C 디바이스는 I2C로 읽기나 쓰기 후에 현재의 주소 위치를 자동으로 증가를 하는데 PCA9685는 자동으로 증가를 할 것인가를 선택 할 수 있습니다. 기본 값은 증가를 하지 않도록 되어 있는데 자동 증가로 설정 합니다. 초기화 시에 0x30으로 설정을 합니다.

Mode register 2 (ADDR : 0x01, MODE2)

BIT [7-5] reserved.
BIT [4] INVRT
    0 : Output logic state not inverted.
    1 : Output logic state inverted.
BIT [3] OCH
    0 : Output change on STOP command.
    1 : Output change on ACK.
BIT [2] OUTDRV
    0 : The 16 LEDn outputs are configured with an open-drain structure.
    1 : The 16 LEDn outputs are configured with a totem pole structure.
BIT [1-0] OUTNE
    00 : When nOE=1 (output drivers not enable), LEDn = 0
    01 : When nOE=1 (output drivers not enabled:
    1X : When nOE=1 (output drivers not enabled), LEDn=high-impedance.

MODE2 레지스터에서는 BIT[2]는 블럭다이어그램에서 설명을 했던 PCA9685의 출력에 대한 설정으로써 Adafruit사의 PCA9685는 하드웨어에서 오픈 드레인으로 사용할 수 있도록 설계가 되어 있지 않기 때문에 토템-폴(totem-pole) 방식으로만 설정 해야 합니다.
아두이노에서 많이 사용하는 MG996R 서보모터의 경우에 PWM의 진폭은 서보모터의 전원(4.8V ~ 7.2V) 입니다. 만약 PCA9685를 아두이노가 아닌 3.3V MCU나 라즈베리파이 보드의 경우에 PCA9685의 VCC 전원은 3.3V로 전원을 인가해야 합니다. PCA9685의 VCC가 3.3V 일 때 토템-폴(totem-pole) 출력은 3.3V 입니다. (대부분은 3.3V PWM에서 동작 됩니다. 서보모터 내부에 있는 칩 규격으로 확인해야 하나 관련 데이터시트를 구하기는 거의 불가능에 가깝습니다. 그러므로 실험을 통해서 확인을 하는 방법 밖에 없습니다.)

LED0_ON_L (ADDR : 0x06)

BIT [7:0] LEDn_ON count for LED0, 8 LSBs

LED0_ON_H (ADDR : 0x07)

BIT [4] LED0 full ON
BIT [3:0] LEDn_ON count for LED0, 4 MSBs

LED0_OFF_L (ADDR : 0x08)

BIT [7:0] LEDn_OFF count for LED0, 8 LSBs

LED0_OFF_H (ADDR : 0x09)

BIT [4] LED0 full OFF
BIT [3:0] LEDn_OFF count for LED0, 4 MSBs

 

위 4개의 레지스터는 PWM 채널 0번의 LED OFF와 LED ON의 12비트 카운터 값을 설정 합니다. 위와 같이4개의 쌍으로 이루어져 있으며, 이어서 15개가 있습니다.

ALL_LED_ON_L (ADDR : 0xFA)

BIT [7:0] LEDn_ON count for ALL_LED, 8 LSBs

ALL_LED_ON_H (ADDR : 0xFB)

BIT [4] ALL LED full ON
BIT [3:0] LEDn_ON count for ALL_LED, 4 MSBs

ALL_LED_OFF_L (ADDR : 0xFC)

BIT [7:0] LEDn_OFF count for ALL LED, 8 LSBs

ALL_LED_OFF_H (ADDR : 0xFD)

BIT [4] ALL_LED full OFF
BIT [3:0] LEDn_OFF count for ALL_LED, 4 MSBs

 

위 4개 레지스터는 PWM 16개 채널을 동시에 같은 값으로 출력을 할 때 사용을 합니다. 보통 PWM9385를 초기화 할 때 출력 전체를 OFF할 때 ALL_LED_OFF_H 레지스터에 0x10을 씁니다.

PRE_SCALE (ADDR : 0xFE)

BIT [7:0] prescaler to program the PWM output frequency

 

프리스케일 레지스터로써 프리스케일 값을 설정 합니다. 프리스케일 값은 앞 장의 공식으로 구합니다.

3.2. 디바이스 드라이버 작성

PCA9685를 통해 서보모터를 제어하기 위해서는 가장 먼저 서보모터의 규격을 알아야 합니다. 여기에서는 다음과 같은 규격의 서보모터 예 입니다.

  • PWM 주파수 : 50 ~ 330 Hz
  • 180도 (500 ~ 2500 us, 중앙(center 90도 : 1500 us)
  • dead zone : 3 ~ 6 us

취미용(RC 서보모터) 서보모터는 PWM 주파수 200 Hz으로 제어를 하면 대부분 동작을 합니다. 이 장에서는 200 Hz를 예로 설명을 합니다.

프리스케일 계산

25 MHz에 PWM 주파수 200Hz를 공식에 넣어 계산을 하면 30(0x1E)이 됩니다.

PWM9685 초기화

  • MODE1 레지스터에 0x30를 씁니다. (레지스터 주소를 자동으로 증가모드로 설정 합니다.)
  • MODE2 레지스터에 0x04를 씁니다. (PWM 출력 모드를 토템-폴로 설정 합니다.)
  • ALL_LED_ON_L, ALL_LED_ON_H 레지스터에 0x00를 씁니다.
  • ALL_LED_OFF_L 레지스터에 0x00를 씁니다.
  • ALL_LED_OFF_H 레지스터에 0x10를 씁니다. (16채널의 출력을 강제로 오프(LOW, 0V)로 합니다.)
  • MODE1 레지스터의 BIT[4](0 : normal mode, 1 : sleep mode)가 슬립모드(sleep mode)에 있는지 검사를 하여 일반모드(normal mode)에 있으면 슬립모드로 설정 합니다.
  • PRE_SCALE 레지스터에 프리스케일 값(30, 0x1E) 값을 씁니다. (PRE_SCALE 값은 PCA9685가 슬립모드에서만 변경할 수 있습니다.)
  • MODE1 레지스터의 BIT[4]를 0(normal mode)으로 변경 합니다.

서보모터 위치 제어

서보모터 위치 제어 함수는 채널과 PWM ON(HIGH) 시간(us)을 파라미터로 받습니다. PWM ON 시간을 카운터 값은 다음과 같은 공식으로 값을 구합니다.

먼저 1 카운터의 us 시간을 구합니다.

내부 클럭 25,000,000 Hz 일 때 계산식을 다음과 같이 정리 합니다. (on_counter는 PWM ON의 카운터 값 입니다.)

PCA9685의 채널 레지스터 LEDx_ON_L, LEDx_ON_H 레지스터에 on_counter 값을 LEDx_OFF_L, LEDx_OFF_H 레지스터에 off_counter 값을 씁니다. (x는 0 ~ 15까지 PCA9685의 채널 번호 입니다.)

댓글