ESP32보드에서 PWM으로 서보모터 제어해 보기

ESP32보드에서 PWM으로 서보모터 제어해 보기

1. 서보모터와 PWM 제어 배경지식

이전 글에서 PWM 방식을 이용하여 라즈베리 파이 피코 보드에서 서보모터를 제어하는 방법을 아주 소개한 바 있었는데 (https://blog.naver.com/mythee1/223186947086) 서보모터 제어가 처음인 경우 이 글을 참조하면 좋을듯하다.

해당 글에서는 서보모터를 사용하기 위해 알아야 하는 배선 연결 방법, 각도 제어에 사용하는 PWM의 제어 원리, 서보모터의 Datasheet에 대해서도 소개했었다.

그리고 우리가 흔하게 구입하곤 하는 중국산 서보모터들(50Hz)의 경우, 정확한 이유는 알 수 없지만 Datasheet에 제시된 것보다 실제에서는 Datasheet 보다 좀 더 넓은 범위의 펄스폭 값을 주어야 0에서 180도 범위를 제어 가능한 것도 다음과 같이 자세히 소개한 바 있었다.

2. ESP-32에서 PWM 제어로 서보모터 제어하기

ESP32보드는 라즈베리 파이 피코 보드와 동일하게 마이크로 파이썬을 지원하기 때문에, 기존에 마련해둔 코드로 ESP32 보드에서 PWM 방식으로 서보모터를 제어를 시도해 보았다. 참고로, ESP32에서는 출력이 가능한 모든 GP 핀들에 PWM을 사용할 수 있다.

코드는 기존에 사용하던 코드를 그냥 사용하되, PWM 배선을 위한 핀 만 배선이 간결해지도록 GND, VCC와 가까운 GP4로 변경하였다.

사용한 코드는 다음과 같다.

import machine
import utime

servo = machine.PWM(machine.Pin(4))
servo.freq(50)
while True:
print ("1, 0 degree")
      servo.duty_u16(3276)
      utime.sleep(2)
print ("1.5, 90 degree")
      servo.duty_u16(4915)
      utime.sleep(2)
print ("2.0, 180 degree")
      servo.duty_u16(6553)
      utime.sleep(2)

3. 문제점 및 원인

이렇게 ESP32에서 PWM을 이용한 서보모터 동작을 시도한 결과는 다음과 같다.

그런데, 핀 번호에 따라 동작이 조금 더 원활한 경우도 있지만, 동작이 원활하지 못하다.

원인을 찾아본 결과, ESP-32 보드에서 VCC 용으로 연결한 전원은 3.3V인데 반해,

SG90이나 MG90 같은 서보모터는 동작 전압이 4.8~6V인 때문으로 파악되었다.

즉, 이러한 현상은 내가 사용하는 ESP32 개발 보드가 외부용 전원으로 3.3V만을 제공하기 때문에, 전압이 낮아 생기는 문제인 것으로 보였다.

4. 대안과 결과

전원 부족의 문제를 해결하기 위해, 고민하다가 찾아낸 방법은 VCC 대신 Vin을 전원으로 이용하는 것이었다.

즉, 내가 사용한 ESP32 개발 보드가 공식적으로는 3.3V만을 제공하지만, USB로 들어오는 전압을 그대로 나타내주는 VIN이 있었고, USB는 거의 5V인 것을 활용하는 방법이다.

위에서 사용했던 전 원판을 다음과 같이 VIN으로 변경하여 연결하고,

배선의 편의를 위해 다음 사진과 같이 GND를 VIN 옆으로 이동하여 연결하고, PWM 출력용 핀도 GP13번으로 변경하였다. ESP-32에서 출력에 사용할 수 있는 핀들은 모두 PWM을 지원하므로 아무 문제가 없다.

PWM 출력용 핀 이 변경되었으므로, 코드도 당연히 다음과 같이 핀 번호를 변경해 주었다.

그리고 이들 핀들에 연결된 배선은 서보모터와 다음과 같이 연결되었다.

그리고 조금 더 각도로의 동작을 보여주도록 코드를 다음과 같이 조정했다.

import machine
import utime

servo = machine.PWM(machine.Pin(13))
servo.freq(50)
while True:
for i in range(30) :
      dutypercent=i*0.1/20
      output=int(round(dutypercent*65535, 0))
      angle=(i*0.1-0.5)/(2.5-0.5)*180
if angle<0:
          angle=0
if angle>180:
          angle=180
print (i*0.1, "msec  ", dutypercent*100,"%,  PWM put =", output,"Expected Angle = ",angle)
      servo.duty_u16(output)
      utime.sleep(1)

결과적으로 이렇게 전 원판을 변경한 상태에서 동작하는 모습은 다음과 같이 원활하다.