쿼드콥터 제작기 11 - PPM과 아두이노 Interrupt

Posted by dw0rdptr
2016. 3. 1. 22:37 IoT/QuadCopter

hobbyking에서 리시버와 조종기를 구매했다. 모델명은 HK-T6A V2 Transmitter&Receiver 2.4Ghz

송신기에서는 PWM신호를 직접 전달하는데 6채널 송신기의 경우 채널별로 에일러론(CH1), 엘리베이터(CH2), 쓰로틀(CH3), 러더(CH4) 외 두가지 PWM 신호, 총 6가지 PWM신호를 포함하게 되는 PPM 신호를 송신한다. 수신기에서는 송신된 무선전파를 수신하여 PPM신호을 검출한다. 검출한 PPM신호를 MCU(컨트롤러 보드)로 전달하고, MCU에서는 PPM신호에서 개별 채널의 PWM신호를 뽑아내는 것이 기본적인 RC PPM신호의 사용이다.

PWM이 Pulse Width Modulation(펄스 폭 변조)라면, PPM은 Pulse Positon Modulation(펄스 위치 변조)인 것이다.


   표준 RC 수신기 block diagram

출처 : http://skymixer.net/electronics/84-rc-receivers/78-rc-ppm-signal

위 그림에서 PPM Frame Decoder가 MCU, 즉 아두이노라고 생각하면 된다. 

그림처럼 아두이노(MCU)와 수신기를 연결해야 하는데 그전에 먼저 송신기와 수신기를 바인딩 시켜야 한다. 이건 제품마다 다르니 제품명을 검색해서 찾으면 된다.


위처럼 5v와 GND핀에 연결, 각 채널 시그널핀은 디지털핀에 연결하면 아두이노와 수신기 연결은 끝.

이제 문제는 아두이노에서 어떻게 PPM신호를 해석해 PWM신호를 뽑아내냐는 것인데..이는 아두이노의 Interrupt로 간단하게 구현 가능하다.


인터럽트에 대해 간단히 설명을 하자면, 지정된 핀의 상태가 원하는 조건과 일치하면 미리 등록한 인터럽트 callback 함수, 즉 ISR (Interrupt Service Routines 인터럽트 서비스 루틴)을 자동으로 호출해주는 기능이다. 이때 실행중이던 loop() 함수 안의 루틴은 인터럽트 콜백 함수가 끝날 때 까지 대기상태가 된다.

쉽게말해 어떤 핀의 상태가 특정한 조건이 되면 loop()를 멈추고 그동안 사용자가 등록한 함수(ISR)를 실행하고 등록한 함수가 끝나면 다시 loop()함수로 되돌아오는게 인터럽트이다.


다음 단계를 통해 PPM신호의 개별 채널을 감지하고 개별 채널의 PWM ON(High)시간을 측정할 수 있다.


1. 상승에지 감지(Rising Edge Sense)를 하면 인터럽트 서비스 루틴이 실행됨

2. Timer1의 카운터값을 기록하고, 센싱모드를 하강에지감지(Falling edge sense)로 바꾼다.

3. 인터럽트 서비스 루틴을 빠져 나간다.

4. 하강에지 감지(Falling Edge Sense)를 하면 인터럽트 서비스 루틴이 실행된다.(위에서 하강에지감지 모드로 바꾸었기 때문)

5. Timer1의 카운터값을 기록하고, 센싱모드를 상승에지감지(Rising Edge sense)로 바꾼다.

6. 펄스의 ON시간을 계산한다.(펄스의 ON 시간 계산하기: 두가지 경우가 있음)

// 경우1: 하강에지 시각이 상승에지보다 후(뒤)일때 : ON시간 = (후 - 전)

// 경우2: 하강에지 시각이 상승에지보다 전(앞)일때 : ON시간 = (카운터최대값 +전 - 후)

7. 인터럽트 서비스 루틴을 빠져 나간다.

8. 상승에지 인터럽트 감지하면, 위의 1번부터 차례대로 진행.(무한 반복)


출처 : AVR과 RC PPM 신호 (3편) - PPM 신호감지를 위한 AVR을 소스코드

좀더 자세하게 알고 싶으면 위 출처의 링크를 보면 된다.


어찌저찌 구현을 했는데..

예상치 못한 문제가 생겨버렸다. RC신호를 받으려고 인터럽트 서비스 루틴을 실행하는 중에는 PID제어값, 특히 D제어값이 이상하게 튀어버린다. 시소테스트를 하는 도중 틱 틱 소리가 났었는데 D제어값이 튄것이 그 이유였다.


500~600이상 D제어 값이 튀어버린다.


그래서 여기저기 도움을 청하고 구글링을 하다 내린 결론은 아두이노가 RC 신호 수신 대기시간동안은 PID제어를 못한다는 것이었다.

그래서 서브 아두이노 보드를 추가해 수신기를 연결하고 RC PPM 신호를 받아 해석한 각 PWM 신호 범위를 필요에 맞게 스케일링 한 뒤 보드간 통신으로 PID제어와 모터 출력을 담당하는 메인 아두이노 보드로 넘겨주는 방법으로 해결했다.


자세한 방법은 다음포스팅에~