피코 보드에서 PWM으로 아날로그 형태의 신호 출력하기

피코 보드에서  PWM으로 아날로그 형태의 신호 출력하기

앞선 글들에서 라즈베리파이 피코 보드를 이용해 아날로그 신호를 입력하는 방법을 소개했다.

https://blog.naver.com/mythee1/223185316470

그러면 이와 반대로 라즈베리 파이 피코 보드에서 아날로그 값을 출력하는 것은 어떻게 할까?

방법은 PWM (Pulse Width Modulation)을 이용하는 것이다.

참고. 라즈베리파이 피코 보드에서 디지털 입력과 디지털 출력 방법

디지털 출력 : mypicoled=machine.pin(핀 번호, machine.Pin.OUT)

디지털 입력 : mysensor = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_DOWN)

라즈베리파이 피코는 내부적으로 디지털 방식으로 신호를 처리하기 때문에, 곧바로 아날로그 값을 출력할 수는 없기 때문에, 내보내어야 할 신호를 마치 수학의 미분과 유사하게 신호를 여러 개의 펄스로 나누고, 이들 각각

의 펄스의 값을 On/Off로 조절하여 아날로그와 유사한 신호를 구현하는데, PWM에서는 이들 각각의 펄스의 폭을 조절하는 방식으로 Duty를 조절하게 되므로 PWM(Pulse Width Modulation)이라고 부르며, 이러한 방법을 통해 아날로그와 유사한 신호를 출력하게 되는 것이다.

이처럼 출력신호를 1초당 몇 개의 펄스로 나누는지를 주파수 (frequency)라고 하는데, 장치별로 사용가능한 주파수가 정해져 있는 경우도 많으며, 다음과 같이 Datasheet에 해당 내용이 공개되는 게 일반적이다. 다음의 예는 SG90 서보 모터의 Datasheet에서 발췌한 내용이다.

실제로 PWM방식으로 해당 장치를 제어하려면 하나의 펄수 주기동안 얼마만큼 펄스를 유지할 것인가가 중요한데, 하나의 펄스 주기동안 얼마나 펄스를 Active 상태로 유지할 것인가를 Duty라고 하며, 이 duty 값으로 PWM 장치들을 제어하게 된다.

예를 들어, PWM을 이용하는 SG90 서보모터의 경우 다음과 같이 , datasheet에는 1msec의 폭을 갖는 펄스를 주면, 0도 위치로, 2msec의 폭을 가지는 펄스를 주면 180도 방향이 되도록 회전하게 되는 것이 제시되어 있다.

이를 이용하여 PWM출력을 하는 경우, 다음과 같이 된다.

이론상 0도로 동작되도록 PWM 핀으로 실제 출력되어야 하는 duty값은 : 65535 x 1.0 / 20 = 3276

이론상 90도로 동작되도록 PWM 핀으로 실제 출력되어야 하는 duty값은 : 65535 x 1.5 / 20 = 4915

이론상 180도로 동작되도록 PWM 핀으로 실제 출력되어야 하는 duty값은 : 65535 x 2.0 / 20 = 6553

<참고사항>

실제 test해 보면 SG90의 경우 오차 및 제작사 설게치 변경 등으로 인해 위의 값을 그대로 사용하면 0도에서 180도까지 동작하지는 않는다. 실제로는 0.5msec~2.5 msec 범위로 값을 확장해 주어야 0도에서 180도까지 동작한다. 때문에 실제로 필요한 PWM duty 출력값은 다음과 같다.

실제 0도로 동작되도록 PWM 핀으로 실제 출력되어야 하는 duty값은 : 65535 x 0.5 / 20 = 1638 보다 작은값

실제 180도로 동작되도록 PWM 핀으로 실제 출력되어야 하는 duty값은 : 65535 x 2.5 / 20 = 8192 보다 큰값

라즈베리파이 피코 보드에는 총 16개의 PWM 채널이 있다.

다음 그림을 살펴보면 보드의 왼쪽과 오른쪽의 GND와 시스템 전압을 제외한 거의 모든 핀들을 PWM 용도로 사용할 수 있기는 하지만, 잘 살펴보면 보드 왼쪽 핀들의 PWM 번호 일부가 보드 오른쪽 핀들의 PWM 번호와 일치하는 것을 발견할 수 있다. PWM 선언하는 경우에 해당 핀들은 같은 PWM으로 선언된 핀들과 동등해지고, 같은 PWM 번호를 가지는 핀들은 중복해서 사용할 수 없게 된다. 이 때문에 여러 아날로그 출력을 연결하더라도 최대 16개의 핀을 사용할 수 있게 되며, 이 때문에 여러 아날로그 출력을 연결하더라도 최대 16개의 핀을 사용할 수 있게 된다.

PWM 사용을 하려면 먼저 사용할 핀을 PWM 출력으로 선언해 주어야 한다. 선언하는 방법은 다음과 같다.

변수명 = machine.PWM(machine.Pin(GP 핀번호))

그다음에는 1초당 얼마나 많은 수의 펄스로 제어할지를 지정해 주어야 한다. 다음과 같이 frequency 명령으로 지정한다. 인자로 사용되는 값은 장치마다 제조사에서 지정하는 값이 있는 경우도 있고, 크게 영향을 받지 않는 경우도 있다. 출력을 보낼 장치의 제조사에서 발행한 Data sheet를 참조해야 한다.

변수명.freq(1000)

실제 PWM 출력 명령은 다음과 같이 duty 명령을 사용한다. 16bit (0~56535사이 정수)로 출력이 이루어진다.

변수명.duty_u16( )

가변저항을 이용하여 LED를 PWM으로 조절하는 예제는 다음과 같다.

import machine
import utime

register = machine.ADC(26)
led = machine.PWM(machine.Pin(15))
led.freq(1000)
while True:
 led.duty_u16(register.read_u16())

이처럼 frequency를 1000으로 설정한 경우의 동작 상태는 다음과 같다.

가변저항을 조절하면 밝기가 변화하는 것으로 볼 수가 있다. 또한 인간의 시각적인 입장에서는 차이를 느낄 수 없을 만큼 충분히 큰 수인 1000개의 펄스로 구성되었므로 각 펄스의 변화에 따른 밝기의 변화를 시각적으로는 느끼기 어렵다.

한편 frequency를 10으로 설정한 경우의 동작 상태는 다음과 같다.

(참고로 위의 마이크로 파이썬 코드의 경우 입력 가능한 frequency 최소값은 8 이었다.)

이 경우에도 가변저항을 조절하면 밝기가 변화하지만, 초당 10개 정도의 펄스로 구성되다 보니, 시각적으로 깜빡거리는 것을 인지할 수가 있었다.