2016년 7월 21일 목요일
Firmata를 사용해 라즈베리 파이에서 아두이노 제어하기 (Controlling Arduino from Raspberry Py using Firmata)
아두이노와 라즈베리 파이를 시리얼 포트롤 통해 연결하면 firmata를 사용해 라즈베리 파이에서 아두이노의 핀들을 제어할 수 있다. 아두이노와 라즈베리 파이를 시리얼 포트로 연결하는 방법은 이전 포스트(라즈베리 파이와 아두이노를 시리얼 포트로 연결하는 방법들 )를 참고하면 된다.
먼저 아두이노를 설정 해 준다.
Firmata를 사용해 라즈베리 파이에서 아두이노를 제어하려면 아두이노에도 firmata 소프트웨어가 설치되어 있어야 한다.
메뉴의 File -> Examples -> Firmata 에서 StandardFirmata를 오픈해 자신이 사용하는 아두이노에 업로드 해 주면 된다.
다음은 라즈베리 파이에 pyfirmata를 설치해야 한다.
터미널 창에서 아래의 명령을 입력해 주면 된다. 기존에 이미 pip와 pyserial이 설치되어 있다면 첫번째 줄은 건너 뛰어도 된다.
$ sudo apt-get install python-pip python-serial
$ sudo pip install pyfirmata
이제 아두이노를 USB케이블을 사용해 라즈베리 파이에 연결해 주면 /dev 디렉토리에 ttyUSB0 디바이스가 만들어진다. 이 디바이스 이름을 알고 있어야 한다.
만일 라즈베리 파이에 허브를 연결한 다음 여러대의 아두이노를 연결해 주면 각각 /dev/ttyUSB0, /dev/ttyUSB1, /dev/ttyUSB2, .... 식으로 이름이 부여된다.
이제 실제로 라즈베리 파이와 아두이노를 firmata를 사용해 연결해 준다.
$ python
Python 2.7.3 (default, Mar 18 2014, 05:13:23)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from pyfirmata import Arduino, util
>>> board = Arduino('/dev/ttyUSB0')
>>>
위와 같이 에러가 없이 진행되었다면 연결이 성공한 것이다.
이제 아두이노의 디지털 포트는 board.digital[] 리스트를 사용해 제어할 수 있다.
즉 13번핀의 LED를 on/off하고 싶으면 다음과 같이 하면 된다.
>>> board.digital[13].write(1)
>>> board.digital[13].write(0)
>>>
핀의 상태를 읽을 때는 다음과 같다.
>>> print board.digital[3].read()
0
>>>
그런데 핀을 반복적으로 사용해야 하는 경우 매번 board.digital[...] 이렇게 쓰는건 귀찮다. 그 대신 board.get_pin() 함수를 사용해 핀의 reference를 얻어 올 수 있다. 함수의 파라미터 부분에 "[a|d]:[pin#]:[i:o:p:s]" 형태의 스트링을 넘겨줘야 하는데 파라미터는 3개의섹션으로 되어 있고 각 섹션은 콜론(':')으로 구분한다.
첫번째 섹션은 핀이 아날로그(a)인지 디지털(d)인지를 지정한다. 두번째 섹션은 사용할 핀 번호가 된다. 즉 아두이노 우노의 경우 아날로그면 0~5, 디지털이면 0~13 사이의 값이 올 수 있다. 세번째 섹션은 핀 모드를 설정한다. 'i'면 입력, 'o'면 출력, 'p'면 PWM, 's'면 서보가 된다.
이 함수의 리턴값을 변수에 넣어 추후 read, write에 사용하면 된다.
>>> pin13 = board.get_pin('d:13:o')
>>> pin13.write(1)
>>>
>>> pin2 = board.get_pin('d:2:i')
>>> pin2.read()
0
>>>
아날로그 핀에서 값을 읽을 때는 먼저 analog value reporting을 활성화 시켜줘야만 한다. 하지만 그렇게 하면 아두이노가 라즈베리 파이에게 지속적으로 값을 보내게 된다. 라즈베리 파이에서 값을 계속 읽어내지 않으면 시리얼 통신을 막아버려 스크립트가 정상적으로 동작하지 못하게 만들어 버린다. 그러므로 정상적으로 값을 읽기 위해서는 iterator 스레드를 사용하는 것이 유용하다.
>>> it = util.Iterator(board)
>>> it.start()
>>> board.analog[0].enable_reporting()
>>> board.analog[0].read()
>>> it.start()
>>>
아날로그 값 리포팅을 멈추게 하려면 disable_reporting() 메소드를 호출하면 된다.
Labels:
라즈베리 파이,
시리얼 통신,
아두이노,
임베디드,
arduino,
Embedded,
embedded development,
firmata,
pyfirmata,
Raspberry Pi
라즈베리 파이와 아두이노를 시리얼 포트로 연결하는 방법들 (Methods of connecting Raspberry Pi and Arduino using serial port)
라즈베리 파이와 아두이노를 시리얼 포트로 통신을 할 수 있도록 연결하는 방법을 소개한다.
가장 쉬운 방법은 라즈베리 파이의 USB 포트에 아두이노를 USB케이블로 연결하는 것이다.
이 경우는 라즈베리 파이에서 아두이노 IDE로 스케치를 작성해 아두이노로 바로 다운로드도 가능하다. 그리고 라즈베리 파이의 시리얼 포트 디바이스명은 '/dev/ttyUSB0'가 된다. 즉 라즈베리 파이에서 시리얼 포트로 데이터를 보내려면 아래와 같은 식으로 해야 한다.
$ python
Python 2.7.3 (default, Mar 18 2014, 05:13:23)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> ser = serial.Serial('/dev/ttyUSB0', 115200)
>>> ser.open()
>>> ser.write("Hello")
>>> ser.close()
>>>
두번째로는 라즈베리 파이의 Tx/Rx핀과 아두이노의 Tx/Rx핀을 직접 연결해 주는 것이다.
Rx/Tx를 서로 크로스로 연결해주면 되는데 단 주의해야 하는 것은 라즈베리 파이의 I/O 핀들은 5V tolerant 하지 않다는 것이다. (즉 라즈베리 파이의 I/O핀에 5V 전압을 가하면 포트가 죽어버릴 수 있다) 그러므로 라즈베리 파이의 Tx -> 아두이노의 Rx 연결(위의 그림에서 노란색 케이블)은 그냥 직접 연결해 줘도 되지만, 아두이노의 Tx -> 라즈베리 파이의 Rx는 신호 레벨을 5V에서 3.3V로 변환해 주는 회로가 필요하다. 전용 level shifter IC를 사용할 수 있지만 여기서는 그냥 가장 간단하게 저항을 사용해 전압 분배회로를 만들어 연결해 줬다. 위의 그림에서 브레드보드에 있는 두개의 저항이 전압 분배 회로이다. 여기서는 1.5K, 3.3K 저항을 사용했다.
이 경우 라즈베리 파이의 시리얼 포트 디바이스명은 '/dev/ttyAMA0'가 된다. 즉 사용하려면 /dev/ttyAMA0 디바이스를 오픈해야만 한다.
$ python
Python 2.7.3 (default, Mar 18 2014, 05:13:23)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> ser = serial.Serial('/dev/ttyAMA0', 115200)
>>> ser.open()
>>> ser.write("Hello")
>>> ser.close()
>>>
브레드 보드 대신 만능기판에 작은 컨버터 보드를 만들어 사용하면 편하다.
세번째로는 라즈베리는 Tx/Rx핀을 사용하고 아두이노는 소프트웨어 시리얼을 사용해 연결해 줄 수도 있다. 아두이노 우노의 경우 하드웨어 시리얼 포트가 한개밖에 없어 시리얼 포트를 다른 용도로 사용해야만 하는 경우에는 이런 방법을 쓰면 된다.
위의 두번째 그림과 동일하고 단지 아두이노쪽의 핀 번호가 Rx(0), Tx(1) 대신 Rx(6), Tx(7)로 바뀐 것 뿐이다.
이렇게 하는 경우 스케치에서 달라져야 하는 부분은 다음과 같다.
먼저 하드웨어 시리얼을 사용해 아두이노가 라즈베리 파이에게 1초에 한번씩 "Hello"라는 글자를 보내는 경우의 스케치이다.
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.writeln("Hello");
delay(1000);
}
다음은 소프트웨어 시리얼을 쓰는 경우의 스케치이다.
#include <SoftwareSerial.h>
SoftwareSerial mySerial(6, 7); // RX, TX
void setup()
{
mySerial.begin(9600);
}
void loop()
{
mySerial.writeln("Hello");
delay(1000);
}
추가되어야 하는 부분은 빨간색, 변경되어야 하는 부분은 파란색으로 표시해 놓았다.
마지막으로는 USB-to-serial 모듈을 사용해 연결하는 방법이다.
라즈베리 파이에도 하드웨어 시리얼 포트는 한개밖에 없는데 다른 용도로 사용해야 하는 경우 위와 같이 별도의 USB-to-serial 모듈을 사용해 연결해 줄 수도 있다. 위의 그림에 있는 USB-to-serial 모듈의 I/O핀은 5V tolerant하기 때문에 아두이노의 Tx/Rx에 별도의 레벨 컨버팅 회로 없이 바로 연결할 수 있지만 다른 제품의 경우는 I/O핀이 5V tolerant한지 확인하고 연결해 줘야만 한다.
라즈베리 파이에 USB-to-serial 모듈을 여러개 연결해 줄 수도 있고 그 경우 각각의 시리얼 포트는 /dev/ttyUSB0, /dev/ttyUSB1, ...식으로 사용하면 된다.
pi@raspberrypi ~ $ ls /dev/tty*
tty tty12 tty17 tty21 tty26 tty30 tty35 tty4 tty44 tty49 tty53 tty58 tty62 ttyAMA0
tty0 tty13 tty18 tty22 tty27 tty31 tty36 tty40 tty45 tty5 tty54 tty59 tty63 ttyprintk
tty1 tty14 tty19 tty23 tty28 tty32 tty37 tty41 tty46 tty50 tty55 tty6 tty7
tty10 tty15 tty2 tty24 tty29 tty33 tty38 tty42 tty47 tty51 tty56 tty60 tty8
tty11 tty16 tty20 tty25 tty3 tty34 tty39 tty43 tty48 tty52 tty57 tty61 tty9
첫번재 USB-to-serial 모듈을 꼽은 다음 다시 동일한 명령을 입력해 보면 다음과 같이 ttyUSB0가 추가된 걸 확인할 수 있다.
pi@raspberrypi ~ $ ls /dev/tty*
tty tty12 tty17 tty21 tty26 tty30 tty35 tty4 tty44 tty49 tty53 tty58 tty62 ttyAMA0
tty0 tty13 tty18 tty22 tty27 tty31 tty36 tty40 tty45 tty5 tty54 tty59 tty63 ttyprintk
tty1 tty14 tty19 tty23 tty28 tty32 tty37 tty41 tty46 tty50 tty55 tty6 tty7 ttyUSB0
tty10 tty15 tty2 tty24 tty29 tty33 tty38 tty42 tty47 tty51 tty56 tty60 tty8
tty11 tty16 tty20 tty25 tty3 tty34 tty39 tty43 tty48 tty52 tty57 tty61 tty9
두번째 USB-to-serial 모듈을 꼽고 다시 실행해 본 결과이다.
pi@raspberrypi ~ $ ls /dev/tty*
tty tty12 tty17 tty21 tty26 tty30 tty35 tty4 tty44 tty49 tty53 tty58 tty62 ttyAMA0
tty0 tty13 tty18 tty22 tty27 tty31 tty36 tty40 tty45 tty5 tty54 tty59 tty63 ttyprintk
tty1 tty14 tty19 tty23 tty28 tty32 tty37 tty41 tty46 tty50 tty55 tty6 tty7 ttyUSB0
tty10 tty15 tty2 tty24 tty29 tty33 tty38 tty42 tty47 tty51 tty56 tty60 tty8 ttyUSB1
tty11 tty16 tty20 tty25 tty3 tty34 tty39 tty43 tty48 tty52 tty57 tty61 tty9
가장 쉬운 방법은 라즈베리 파이의 USB 포트에 아두이노를 USB케이블로 연결하는 것이다.
이 경우는 라즈베리 파이에서 아두이노 IDE로 스케치를 작성해 아두이노로 바로 다운로드도 가능하다. 그리고 라즈베리 파이의 시리얼 포트 디바이스명은 '/dev/ttyUSB0'가 된다. 즉 라즈베리 파이에서 시리얼 포트로 데이터를 보내려면 아래와 같은 식으로 해야 한다.
$ python
Python 2.7.3 (default, Mar 18 2014, 05:13:23)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> ser = serial.Serial('/dev/ttyUSB0', 115200)
>>> ser.open()
>>> ser.write("Hello")
>>> ser.close()
>>>
두번째로는 라즈베리 파이의 Tx/Rx핀과 아두이노의 Tx/Rx핀을 직접 연결해 주는 것이다.
Rx/Tx를 서로 크로스로 연결해주면 되는데 단 주의해야 하는 것은 라즈베리 파이의 I/O 핀들은 5V tolerant 하지 않다는 것이다. (즉 라즈베리 파이의 I/O핀에 5V 전압을 가하면 포트가 죽어버릴 수 있다) 그러므로 라즈베리 파이의 Tx -> 아두이노의 Rx 연결(위의 그림에서 노란색 케이블)은 그냥 직접 연결해 줘도 되지만, 아두이노의 Tx -> 라즈베리 파이의 Rx는 신호 레벨을 5V에서 3.3V로 변환해 주는 회로가 필요하다. 전용 level shifter IC를 사용할 수 있지만 여기서는 그냥 가장 간단하게 저항을 사용해 전압 분배회로를 만들어 연결해 줬다. 위의 그림에서 브레드보드에 있는 두개의 저항이 전압 분배 회로이다. 여기서는 1.5K, 3.3K 저항을 사용했다.
이 경우 라즈베리 파이의 시리얼 포트 디바이스명은 '/dev/ttyAMA0'가 된다. 즉 사용하려면 /dev/ttyAMA0 디바이스를 오픈해야만 한다.
$ python
Python 2.7.3 (default, Mar 18 2014, 05:13:23)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> ser = serial.Serial('/dev/ttyAMA0', 115200)
>>> ser.open()
>>> ser.write("Hello")
>>> ser.close()
>>>
브레드 보드 대신 만능기판에 작은 컨버터 보드를 만들어 사용하면 편하다.
세번째로는 라즈베리는 Tx/Rx핀을 사용하고 아두이노는 소프트웨어 시리얼을 사용해 연결해 줄 수도 있다. 아두이노 우노의 경우 하드웨어 시리얼 포트가 한개밖에 없어 시리얼 포트를 다른 용도로 사용해야만 하는 경우에는 이런 방법을 쓰면 된다.
위의 두번째 그림과 동일하고 단지 아두이노쪽의 핀 번호가 Rx(0), Tx(1) 대신 Rx(6), Tx(7)로 바뀐 것 뿐이다.
이렇게 하는 경우 스케치에서 달라져야 하는 부분은 다음과 같다.
먼저 하드웨어 시리얼을 사용해 아두이노가 라즈베리 파이에게 1초에 한번씩 "Hello"라는 글자를 보내는 경우의 스케치이다.
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.writeln("Hello");
delay(1000);
}
다음은 소프트웨어 시리얼을 쓰는 경우의 스케치이다.
#include <SoftwareSerial.h>
SoftwareSerial mySerial(6, 7); // RX, TX
void setup()
{
mySerial.begin(9600);
}
void loop()
{
mySerial.writeln("Hello");
delay(1000);
}
추가되어야 하는 부분은 빨간색, 변경되어야 하는 부분은 파란색으로 표시해 놓았다.
마지막으로는 USB-to-serial 모듈을 사용해 연결하는 방법이다.
라즈베리 파이에도 하드웨어 시리얼 포트는 한개밖에 없는데 다른 용도로 사용해야 하는 경우 위와 같이 별도의 USB-to-serial 모듈을 사용해 연결해 줄 수도 있다. 위의 그림에 있는 USB-to-serial 모듈의 I/O핀은 5V tolerant하기 때문에 아두이노의 Tx/Rx에 별도의 레벨 컨버팅 회로 없이 바로 연결할 수 있지만 다른 제품의 경우는 I/O핀이 5V tolerant한지 확인하고 연결해 줘야만 한다.
라즈베리 파이에 USB-to-serial 모듈을 여러개 연결해 줄 수도 있고 그 경우 각각의 시리얼 포트는 /dev/ttyUSB0, /dev/ttyUSB1, ...식으로 사용하면 된다.
pi@raspberrypi ~ $ ls /dev/tty*
tty tty12 tty17 tty21 tty26 tty30 tty35 tty4 tty44 tty49 tty53 tty58 tty62 ttyAMA0
tty0 tty13 tty18 tty22 tty27 tty31 tty36 tty40 tty45 tty5 tty54 tty59 tty63 ttyprintk
tty1 tty14 tty19 tty23 tty28 tty32 tty37 tty41 tty46 tty50 tty55 tty6 tty7
tty10 tty15 tty2 tty24 tty29 tty33 tty38 tty42 tty47 tty51 tty56 tty60 tty8
tty11 tty16 tty20 tty25 tty3 tty34 tty39 tty43 tty48 tty52 tty57 tty61 tty9
첫번재 USB-to-serial 모듈을 꼽은 다음 다시 동일한 명령을 입력해 보면 다음과 같이 ttyUSB0가 추가된 걸 확인할 수 있다.
pi@raspberrypi ~ $ ls /dev/tty*
tty tty12 tty17 tty21 tty26 tty30 tty35 tty4 tty44 tty49 tty53 tty58 tty62 ttyAMA0
tty0 tty13 tty18 tty22 tty27 tty31 tty36 tty40 tty45 tty5 tty54 tty59 tty63 ttyprintk
tty1 tty14 tty19 tty23 tty28 tty32 tty37 tty41 tty46 tty50 tty55 tty6 tty7 ttyUSB0
tty10 tty15 tty2 tty24 tty29 tty33 tty38 tty42 tty47 tty51 tty56 tty60 tty8
tty11 tty16 tty20 tty25 tty3 tty34 tty39 tty43 tty48 tty52 tty57 tty61 tty9
두번째 USB-to-serial 모듈을 꼽고 다시 실행해 본 결과이다.
pi@raspberrypi ~ $ ls /dev/tty*
tty tty12 tty17 tty21 tty26 tty30 tty35 tty4 tty44 tty49 tty53 tty58 tty62 ttyAMA0
tty0 tty13 tty18 tty22 tty27 tty31 tty36 tty40 tty45 tty5 tty54 tty59 tty63 ttyprintk
tty1 tty14 tty19 tty23 tty28 tty32 tty37 tty41 tty46 tty50 tty55 tty6 tty7 ttyUSB0
tty10 tty15 tty2 tty24 tty29 tty33 tty38 tty42 tty47 tty51 tty56 tty60 tty8 ttyUSB1
tty11 tty16 tty20 tty25 tty3 tty34 tty39 tty43 tty48 tty52 tty57 tty61 tty9
Labels:
라즈베리 파이,
시리얼 통신,
시리얼 포트,
아두이노,
arduino,
Raspberry Pi,
serial communication,
Serial Port,
software serial,
usb-to-serial
피드 구독하기:
글 (Atom)




