[Tinker Board S] GPIO이용#2 - Digital I/O (Python/Node.js) 및 PWM 설명/RPI비교
Small Devices/Tinker Board S 2018. 8. 17. 14:28본 체험 제품은 아이씨뱅큐(주)에서 진행하는 무상 체험단 활동으로 작성한 것입니다.
이전 포스팅(http://alnova2.tistory.com/1225) 에서는 ASUS Tinker Board S 의 GPIO 활용을 위한 환경과 C/C++로 되어 있는 라이브러리를 설명했었습니다. 그리고 간단한 Digital I/O에 대해서 Raspberry Pi와 비교하여 C/C++로 실험을 했었습니다. 이번 포스팅에서는 Digital I/O에 대해서 Python/Node.js 프로그래밍 언어로 사용하는 것과 PWM활용에 대해서 실험 및 Raspberry Pi와 비교를 해보도록 하겠습니다.
1.Digital I/O 활용하기(Python/Node.js Case)
[Python에서의 Digital I/O]
ASUS Wiki에 보면 Python의 경우 어느 정도 공식적으로 지원하는것 같습니다. (https://tinkerboarding.co.uk/wiki/index.php/GPIO#Python) 에 Python 지원을 위한 라이브러리 설치 방법이 나와 있습니다. 다음과 같이 설치 합니다.
$ wget http://github.com/TinkerBoard/gpio_lib_python/archive/sbc/tinkerboard/python.zip
$ sudo apt-get install python-dev
$ unzip python.zip
$ cd gpio_lib_python-sbc-tinkerboard-python/
$ sudo python setup.py install
sudo python setup.py install 하게 되면 python모듈이 install됩니다. test폴더에는 샘플 코드들이 있는데요, wiki에서 각 예제에 대한 설명을 보실수 있습니다. 그리고 https://github.com/sabrigultekin/Asus-Tinker-Board 에서 더 많은 예제를 볼수 있다고 합니다. 이 포스팅에서 살펴볼 예제는 sabrigultekin 에서 Led Blink를 변경해서 살펴보겠습니다. 이전 포스팅에서와 같이 LED를 동일하게(3번 물리핀에) 연결합니다. 다음은 LED 를 1초 간격으로 온/오프하는 Python코드 입니다.
import ASUS.GPIO as GPIO import time GPIO.setwarnings(False) GPIO.setmode(GPIO.ASUS) LED = 252 GPIO.setup(LED,GPIO.OUT) try: while True: print "led on" GPIO.output(LED,GPIO.HIGH) time.sleep(1) print "led off" GPIO.output(RED,GPIO.LOW) time.sleep(1) except KeyboardInterrupt: GPIO.cleanup() |
이전 포스팅에서는 3번 물리핀에 대한 wiringPi Pin인 8번을 C/C++ 프로그램에서 설정 했었습니다. Python의 경우 setmode 설정값에 따라서 다른 번호를 넣어야 합니다. 다음의 GPIO Pinout에서 보드 pin에 대한 GPIO.ASUS의 번호를 알 수 있습니다. 물리핀 3번에 대해서 GPIO.BOARD의 경우 3을, GPIO.ASUS일 경우 252를 설정합니다.
Raspberry Pi 도 Python의 경우 동일합니다. Raspberry Pi의 경우 별도 프로그램 설치는 불필요합니다.
다음은 Raspberry Pi에서 Python으로 LED를 온/오프 하는 예제 입니다. 앞의 예제와의 비교를 위해서 Tinker Board 코드 같이 보여드리겠습니다. LED번호는 GPIO.BCM모드의 경우 2번이 됩니다. 둘다 어떤 번호를 할당해야 할지는 gpio readall 명령어에 보여지는 번호를 참조해서 활용하면 됩니다.
Tinker Board S |
Raspberry Pi 3 B |
import ASUS.GPIO as GPIO import time GPIO.setwarnings(False) GPIO.setmode(GPIO.ASUS) LED = 252 GPIO.setup(LED,GPIO.OUT) try: while True: print "led on" GPIO.output(LED,GPIO.HIGH) time.sleep(1) print "led off" GPIO.output(LED,GPIO.LOW) time.sleep(1) except KeyboardInterrupt: GPIO.cleanup() |
import RPi.GPIO as GPIO import time GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) LED = 2 GPIO.setup(LED,GPIO.OUT) try: while True: print "led on" GPIO.output(LED,GPIO.HIGH) time.sleep(1) print "led off" GPIO.output(LED,GPIO.LOW) time.sleep(1) except KeyboardInterrupt: GPIO.cleanup() |
붉은색 부분을 제외하고는 동일합니다. 아마 Tinker Board에서 Raspberry Pi를 참조한게 아닌가 싶습니다. (유사하게 가려고..)
[node.js에서의 Digital I/O]
Raspberry Pi에서 node.js 관련 모듈은 여러 커뮤니티에서 다양하게 지원하고 있습니다. Raspberry Pi에서 지원되는 node.js 모듈들에 대해서 다음의 사이트에서 각각 비교-정리되어 있습니다.
https://gist.github.com/jperkin/e1f0ce996c83ccf2bca9
Asus Tinker Board S의 경우 https://github.com/FrankWu100/tinker-gpio 이외에는 찾을수가 없었습니다. 따라서 tinker-gpio로 실험해 보겠습니다. Tinker Board에 node.js를 설치하고(이전 포스팅: http://alnova2.tistory.com/1225 를 참고하세요.) 다음의 명령어로 tinker-gpio node.js 모듈을 설치 합니다.
$ npm install tinker-gpio
tinker-gpio 는 digital I/O만 가능해 보입니다. 모듈에서 제공하는 함수는 https://www.npmjs.com/package/tinker-gpio 에서 확인 가능합니다. 다음의 코드를 led.js 에 저장하고 node led.js 명령으로 LED 온/오프를 실행할 수 있습니다.
const gpio=require('tinker-gpio'); const LED=3; gpio.open(LED,"output",(err)=>{ let flag=true; if(!err){ setInterval(()=>{ if(flag){ flag=false; gpio.write(LED,1,()=>{ console.log('Led On'); }); } else { flag=true; gpio.write(LED,0,()=>{ console.log('Led Off'); }); } },1000); } else { console.log('GPIO Open Error'); } }); |
Raspberry Pi의 경우 선택의 폭이 넓습니다. 테스트 예제가 단순히 LED를 온/오프하는 것이기 때문에 onoff라는 간단한 모듈을 이용해서 실험해 보겠습니다. Raspberry Pi에서 node.js를 설치하고(이전 포스팅: http://alnova2.tistory.com/1225 를 참고하세요.) 다음 명령어로 onoff node.js모듈을 설치합니다.
$ npm install onoff
다음의 코드를 led.js로 저장하고 node led.js 명령으로 LED 온/오프를 실행할 수 있습니다.
const Gpio=require('onoff').Gpio; const LED=2; const led=new Gpio(LED,'out'); let flag=true; setInterval(()=>{ if(flag){ flag=false; led.writeSync(1); console.log('Led On'); } else { flag=true; led.writeSync(0); console.log('Led Off'); } },1000); |
[비교후기]
Tinker Board가 Python 을 지원하기 때문에 일반적인 활용은 문제가 없어 보입니다. C/C++로의 개발은 전문적인 측면이 있고 node.js 보다 Python이 많이 사용되기 때문입니다. 하지만 node.js도 꾸준히 SBC 개발에 많이 활용되고 있기 때문에(수많은 RPI 관련 node.js 모듈들이 이를 입증한다고 생각합니다.) node.js 모듈이 활성화 되지 않은 것은 아쉬운 부분입니다. 하지만 다른 측면으로는 raspberry pi 가 그랬던 것처럼 초기에 모듈을 개발하고 공개 함으로써 tinker board 커뮤니티에 기여할수 있는 좋은 기회일수도 있을것 같습니다.
2. PWM 활용하기
PWM 은 Pulse Width Modulation의 약자로, Digital I/O 출력을 Duty와 Period로 나누어서 출력하는 방법입니다.
PWM은 Digital I/O에 펄스 개념을 도입해서 signal의 강약을 아날로그처럼 조정해 주는 방법이라고 간단히 이야기 할 수 있습니다. PWM의 응용은 LED 밝기 조정, DC 모터 속도 조정, 스텝모터 제어 등 Digital I/O를 이용하여 신호 세기를 조정할 수 있는 부분에 적용됩니다.
[C/C++ 활용]
wiringPi의 PWM은 물리PWM와 소프트PWM이 존재합니다. 물리PWM은 특정 하드웨어 핀에서 하드웨어적으로 발생시키는 것이고, 소프트PWM은 소프트웨어적으로 PWM신호를 이뮬레이션 해주는 것입니다. 소프트PWM의 경우 PWM Frequency에 대해서 제한이 있습니다. wiringPi 사이트에서는 100uS 로 pulse width를 제한하고 있으며 100uS보다 더 적게 사용하려고 할 경우 CPU Usage가 급격히 올라간다고 이야기 하고 있습니다. 하지만 100uS 정도도 LED나 motor 제어를 위해서는 충분한 수준입니다.
이본 포스팅은 물리PWM 에 대해서 설명합니다. PWM 물리 핀은 32,33번이고 wiringPi 번호로는 23. 26번 입니다. 26번핀을 이용해 보겠습니다. 다음과 같이 LED를 보드에 연결합니다.
다음의 코드를 pwm.c로 저장하고 gcc -o pwm ./pwm.c -lwiringPi 로 컴파일 합니다. (코드와 물리핀 연결 및 실행 결과는 Tinker Board S와 Raspberry Pi3 b+ 동일합니다. )
아래 예제는 Frequency를 50Hz로 설정하고 PWM 크기를 변경한 예제 입니다. Frequency 설정을 위해서는 pwmSetClock과 pwmSetRange를 조합해야 합니다. pwmSetClock은 기본 주파수 19.2Mhz 를 나누는 값이고, pwmSetClock은 2-4095까지 설정 가능합니다. pwmSetRange는 setClock으로 설정된 clock이 퍼지는 range를 설정하는 것으로 pwmSetRange또한 2-4096까지 가능합니다. pwmSetRange는 pwmSetClock으로 생성된 주파수를 또 분할할수 있게 해줍니다. 결국 다음과 같은 주파수 계산 공식이 나옵니다.
Frequency = 19200000/[pwmSetClock 값]/[pwmSetRange값]
그리고 0~pwmSetRange의 값에 해당하는 값을 pwmWrite 에 설정할 수 있습니다.duty cycle을 설정하는 것인데요. duty cycle은 pwmWrite에 설정한 값에 100/pwmSetRange을 곱한 값이 됩니다. (아래 예에서 200이면 100%)
#include <wiringPi.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> int main (void) { int bright ; printf ("Raspberry Pi wiringPi PWM test program\n") ; wiringPiSetup(); pinMode (26, PWM_OUTPUT) ; pwmSetClock(1920); pwmSetRange(200); for (;;) { for (bright = 0 ; bright < 200 ; bright=bright+4) { pwmWrite (26, bright) ; delay (10) ; } for (bright = 200 ; bright >= 0 ; bright=bright-4) { pwmWrite (26, bright) ; delay (10) ; } } return 0 ; } |
다음은 실행 결과 입니다.
Raspberry Pi 3B의 경우 wiringPi 라이브러리 기반이고 Tinker Board S 와 PWM Pin이 같기 때문에 관련 내용은 동일하게 적용됩니다. 단 프로그램 실행시 sudo 권한이 필요합니다. (즉 sudo ./pwm 으로 실행)
[Python]
Tinker Board S와 Raspberry Pi 모두 Python 기반으로 PWM을 이용 가능 합니다. 이는 wiringPi라는 공통의 라이브러리를 이용했기 때문이죠. 다음은 Tinker Board S와 Raspberry Pi 3B에서 상기 예제외 동일하게 동작하는 프로그램 코드 입니다.
Tinker Board S |
Raspberry Pi 3 B |
import ASUS.GPIO as GPIO import time GPIO.setwarnings(False) GPIO.setmode(GPIO.ASUS) PWMPIN = 239 GPIO.setup(PWMPIN,GPIO.OUT) p=GPIO.PWM(PWMPIN,50); p.start(0); try: while True: for bright in range(0,101,2): p.ChangeDutyCycle(bright) time.sleep(0.01) for bright in range(100,-1,-2): p.ChangeDutyCycle(bright) time.sleep(0.01) except KeyboardInterrupt: GPIO.cleanup() |
import RPi.GPIO as GPIO import time GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) PWMPIN = 12 GPIO.setup(PWMPIN,GPIO.OUT) p=GPIO.PWM(PWMPIN,50); p.start(0); try: while True: for bright in range(0,101,2): p.ChangeDutyCycle(bright) time.sleep(0.01) for bright in range(100,-1,-2): p.ChangeDutyCycle(bright) time.sleep(0.01) except KeyboardInterrupt: GPIO.cleanup() |
Python의 경우 PWM Clock을 GPIO.PWM 함수에서 설정하도록 되어 있습니다. 앞의 C/C++ 예제에서 50Hz 시험했기 때문에 50으로 넣어 줍니다. 그리고 start 함수에서 시작 Duty Cycle을 설정할수 있으며 ChangeDutyCycle로 변경 가능합니다. start와 ChangeDutyCycle의 값은 0-100까지 설정할 수 있습니다. (dutyCycle 0-100%) for문에서 증/감을 2로 하였는데요, 앞의 C/C++ 예제에서는 range가 0-200까지 증감이 4로 되어 있기 때문에 동일한 증감을 보여주려고 2로 하였습니다.
Node.js는 Digital In/Out을 제외하고 Tinker Board에서 지원하지 않습니다. 향후 포스팅은 C/C++ 과 Python을 위주로 진행합니다. 마지막 포스팅에 node.js 모듈 생성하기 위한 예제로 PWM 모듈을 빌드 해보도록 하겠습니다.
다음 포스팅은 i2c 에 대한 내용을 올리려고 합니다~
다음은 GPIO 관련 포스팅입니다.
1. 개발 환경 및 Digital I/O(C/C++) 설명/RPI 비교: http://alnova2.tistory.com/1225
2. Digital I/O 설명(Python/Node.js) 및 PWM 설명/RPI비교 : http://alnova2.tistory.com/1226
3. i2c 설명 및 총평/RPI 비교: http://alnova2.tistory.com/1227
- ASUS 팅커보드 S 공식 구입처: 아이씨뱅큐 http://www.icbanq.com/
- 아이씨뱅큐 공식 카페: http://cafe.naver.com/icbanq
- 아이씨뱅큐 공식 블로그: http://blog.naver.com/icbanq