2016년 11월 28일 월요일

라즈베리 파이에 여러개의 시리얼 포트가 필요할 때 (Use multiple serial port in Raspberry Pi)

라즈베리 파이로 무언가를 만들려고 하다 보면 여러개의 시리얼 포트가 필요한 경우가 있다.  라즈베리 파이에는 기본적으로 두개의 시리얼 포트가 있지만 그 중 하나는 미니포트라 사용에 꽤 신경 써 줘야 하는 부분이 많고,  라즈베리 파이 3의 경우 시리얼포트를 블루투스가 사용하고 있어 블루투스를 동시에 사용하려고 하면 매우 골치 아퍼 진다.  (상세한 내용은 이전 포스트 (라즈베리 파이 3 시리얼/블루투스 문제 (Raspberry Pi 3 UART/Bluetooth problem))를 참고)

그럼 시리얼 포트를 추가할 수 있는 가장 쉬운 방법은 USB-to-Serial converter를 사용하는 것이다. 



시중에 다양한 종류의 제품이 나와 있고 가격도 그리 비싸지 않다.

다만 이 제품들을 사용해서 여러개의  시리얼 포트를 추가하려면 포트당 한개의 USB  포트가 필요하기 때문에 별도의 허브를 붙여줘야 하는 문제가 발생한다. 

그래서 FTDI에서는  USB-to-multiport  Serial  comverter  칩을 제공하고 있다.  FT2232H나 FT4232H  칩을 이용하면 한개의 USB포트로 2개 또는 4개의 시리얼 포트를 확장할 수 있게 된다. 






FT2232H breakout board

그리고  이 경우 가장 큰 장점은 raspbian에 디바이스 드라이버가 이미 포함되어 있어 따로 드라이버를 설치할 필요 없이 라즈베리 파이에 연결만 해 주면 장치를 인식해 곧바로 사용할 수 있다는 것이다. 


위의 화면 캡춰와 같이 breakout board를 연결하기 전에는 없었지만 breakout board를 USB에 연결하고 나면 /dev/ttyUSB0, /dev/ttyUSB1 이 자동으로 추가된다.  (FT2232H의 경우,  FT4232H의 경우는 저 두개 외에 추가로 /dev/ttyUSB2, /dev/ttyUSB3  도 만들어진다.)


FT2232H의 경우 단순히 asynchronous serial (우리가 일반적으로 사용하는 시리얼 통신방식) 뿐 아니고 synchronous serial, FIFO,  SPI,  I2C, Host emulation 등 매우 다양한 방식으로 동작할 수 있기 때문에 여러 핀이 나와 있지만 async serial로 사용하는 경우는 위의 4개 핀만 사용하면 된다. 

테스트를 위해 아래와 같이 uart0의 Tx핀을 uart1의 Rx에 연결해준다.


이제 라즈베리 파이에서 두개의 터미널 창을 열어준다.


minicom 또는 다른 시리얼 터미널 프로그램을 사용해 위쪽의 창은 /dev/ttyUSB0,  아래쪽 창은 /dev/ttyUSB1 포트를 열어준다.


미니컴을 사용하는 경우 디폴트로 하드웨어 플로우 컨트롤을 사용하는걸로 되어 있으므로 그걸 꺼 줘야 한다.  먼저 Ctrl-A 를 누른 다음 'O'를 누르면 위와 같은 메뉴 화면이 나온다.  거기에서 'Serial  port  setup'을  선택  해  준다.


위의 화면이 나오면 'F'  키를 한번 눌러 Hardware Flow Control 부분이 'Yes'로 되어 있는걸 'No'로 바꿔 준다.


위와 같이  되었으면 엔터키를 눌러주고 나서 'Exit'을 선택해주면 된다.  이 과정은 위쪽,  아래쪽 두 터미널 모두 해 줘야 한다.


이제 위쪽 터미널에서 글자를 입력해 보면 아래쪽 터미널에  입력한 글자가 나타나게 된다.  하지만 반대로 아래쪽 터미널에서는 아무리 글자를 입력해도 위쪽 터미널에는 나타나지 않는다.  테스트를 위해 Tx(uart0) -> Rx(uart1) 은 연결했지만 Tx(uart1) -> Rx(uart0)는 연결해 주지 않았기 때문에 그런 것이다. 

현재  aliexpress에서 FT2232H breakout board는 약 $15  정도에 구할 수 있다.  다만 FT4232H breakout board는 aliexpress에서는 찾기가 쉽지 않고 Numato Lab, Mouser 등에서 약 3~4만원 정도(배송비 별도)에 구할 수 있다.

이 디바이스들은 맥,  윈도우용 디바이스 드라이버도 제공되고 있으므로 맥이나 윈도우 환경에서도 여러개의 시리얼 포트가 필요한 경우 유용하게 사용할 수 있다.


Mac Coolterm에서 사용하는 경우  1


Mac  Coolterm에서 사용하는 경우 2

2016년 11월 21일 월요일

macOS Sierra에서 CH340/CH341 사용하기


맥에 Sierra  (Mac OS 10.12)를 설치한 후 CH340/CH341  칩을 사용한 디바이스(알리에서 판매하는 대부분의 저가 아두이노 보드,  ESP8266  기반 보드들이 여기에 들어감)를 연결하면 바로 커널 패닉이 발생해 버린다.




일단 커널 패닉이 발생하면 패닉을 발생시키는 원인이 되는 kext/드라이버를 제거해 줘야 한다.  어떤 kext가 문제를 발생시켰는가는 /Library/Logs/DiagnosticReports  안의 .panic  확장자를 가진 로그 파일에서 확인할 수 있다.
CH340인 경우 보통 wch.usb.usb 가 원인이 된다.
이 kext를 제거하려면 어느 디렉토리에 들어있는가 확인해 줄 필요가 있다.  이 경우 /Sysyem/Library/Extensions 디렉토리 내에 usb.kext라는 이름이지만 불행하게도 이름과 위치가 다를 수도 있다.  이게 찾는 드라이버가 맞는지 확인하고 싶으면 다음의 명령을 사용하면 된다.

$  cat usb.kext/Contents/Info.plists | grep wch.usb.usb

위의 명령을 실행해 무언가 내용이 출력된다면 찾는 파일이 맞다는 것이다.  이제 저 파일을 삭제하고 나면 디바이스를 연결해도 커널 패닉이 발생하지 않는다.  (물론 드라이버가 없으니 장치가 인식되지 않는다)

-----------------------------------------------------------------------------------------------

Mac Sierra에서 사용할 수 있는 CH340/CH341 드라이버가 만들어졌다.  아래 링크에서 다운받아 설치해 주면 된다.

Winchiphead  signed  drivers  for  CH340-CH341,  OS  X  10.9  to  macOS  10.12

The credit goes to the blog 'Playing with bits and bytes

2016년 11월 14일 월요일

Simblee BLE module

아두이노 등으로 작품을 만들 때 가장 골치아픈 부분중에 하나가 블루투스 통신이다.  블루투스 통신  뿐  아니고 스마트폰으로 무언가를 제어하거나 센서 값을 화면에 표시하려면 아두이노쪽 코드 뿐 아니고 안드로이드 또는 iOS  앱을 따로 만들어 줘야만 한다.
하지만 simblee는 이 문제를 다른 방법으로 접근해 간단하게 해결했다.

디바이스 코드 뿐 아니고 스마트폰에 표시될 UI  관련 코드까지 아두이노 UI에서 한번애  다 작성할 수 있게 만들어 버렸다.  즉 스마트폰 화면에 표시할 UI를 simblee에서 직접 보내주고,  스마트폰에서 이벤트가 발생(버튼 클릭 등)하면 그 이벤트에 대한 처리 코드 역시 simblee에 들어있다.



스마트폰은 일종의 웹 브라우져같이  동작해  스마트폰에서 Simblee for mobile앱을 실행시켜 놓으면 웹서버(즉 여기서는 simblee)에서 웹페이지 내용(여기서는 UI  화면)을 받아 화면에 표시해주고 사용자가 버튼이나 링크를 클릭하는 등의 이벤트가 생기면 웹 서버(여기서는 simblee)에 그 이벤트를 전달해 정해진 동작을 처리하게 한다.

그래서 아두이노 스케치에는 기본적으로 setup(), loop() 이렇게 두개의 함수가 있어야만 하는데 simblee  앱에서는 setup(), loop() 외에 추가로 ui(), ui_event() 함수가 있어야 한다.  Simblee는  자신의 정보를 advertise하고 있다가 스마트폰의 Simblee  for  mobile  앱과 연결되면 ui()  자동으로 ui()  함수가 실행되게 된다.  ui()  함수에서 아래와 같이 스마트폰 화면에 표시될 ui  정보를 보내주게 된다.

void ui()
{
  SimbleeForMobile.beginScreen(WHITE,PORTRAIT);
  SimbleeForMobile.drawSwitch(135, 100);
  SimbleeForMobile.endScreen();
}

UI  정보가 스마트폰으로 전송되면 스마트폰 앱 화면에 다음과 같이 수신된 UI가 표시된다.


사용자가 스위치를 토글하면 이벤트가 발생되어 그 이벤트 정보가 simblee로 전달된다.  Simblee는 이벤트를 받으면 자동으로 ui_event()  함수를 호출해 이벤트에 대한 처리를 수행하게 된다.

#include <SimbleeForMobile.h>

uint_8 switch;

void setup()
{
  Serial.begin(9600);
  SimbleeForMobile.deviceName = "Switch";  // SimbleeForMobile  앱에서 'Switch'라는 이름으로 검색됨
  SimbleeForMobile.begin();
}

void loop()
{
    SimbleeForMobile.process();
}

void ui()
{
  SimbleeForMobile.beginScreen(WHITE, PORTRAIT);
  switch = SimbleeForMobile.drawSwitch(135,100);
  SimbleeForMobile.endScreen();
}


void ui_event(event_t &event)
{
  if (event.id == switch) {
    Serial.println(event.value);
  }
}

위의 코드를 Simblee에 다운로드 하고 스마트폰에서 SimbleeForMobile앱을 실행해 'switch'라는 이름의디바이스를 선택하면 위와 같은 화면이 나오고 스위치를 토글하면 아래와 같이 시리얼 포트로 값이 변화하는걸  볼 수 있다.


 좌표계는 아래  그림처럼 좌측 상단이 (0, 0)이 된다.


 Simblee에 연결되는 디바이스마다 화면 크기는 달라진다.  아이폰 5의 경우 폭은 320픽셀,  높이는 570픽셀이 된다.  각 디바이스의 화면 크기는 스마트폰에 연결되면 SimbleeForMobile.screenWidth 과 SimbleeForMobile.screenHeight 에 자동으로 값이 설정된다.