레이블이 Serial Port인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Serial Port인 게시물을 표시합니다. 모든 게시물 표시

2016년 7월 21일 목요일

라즈베리 파이와 아두이노를 시리얼 포트로 연결하는 방법들 (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

2015년 3월 31일 화요일

라즈베리파이 시리얼포트 C 프로그래밍 (Raspberry Pi Serial port programming in C)

Raspberry Pi에서는 기본적으로 UART를 시리얼 콘솔로 사용하게 된다. 하지만 UART를 어플리케이션이 다른 용도로 사용하고자 하는 경우에는 콘솔로 동작하지 못하도록 해 줘야 한다.

먼저 이전 포스트(Raspberry Pi에서 UART를 console이 사용하지 않도록 설정하기)를 참조해 설정을 변경해준다.

C 프로그램에서 UART를 사용하기 위해서는 다음의 헤더 파일을 include 해 준다.

#include <stdio.h>
#include <unistd.h> //Used for UART
#include <fcntl.h> //Used for UART

#include <termios.h> //Used for UART

아래는 UART 설정 코드이다.

// -------------------------
// ----- SETUP USART 0 -----
// -------------------------
// At bootup, pins 8 and 10 are already set to UART0_TXD, UART0_RXD 
// (ie the alt0 function) respectively
int uart0_filestream = -1;

// OPEN THE UART
// The flags (defined in fcntl.h):
// Access modes (use 1 of these):
//   O_RDONLY - Open for reading only.
//   O_RDWR - Open for reading and writing.
//   O_WRONLY - Open for writing only.
//
// O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode. 
//    When set read requests on the file can return immediately with a failure status
//    if there is no input immediately available (instead of blocking). 
//    Likewise, write requests can also return immediately with a failure status 
//    if the output can't be written immediately.
//
// O_NOCTTY - When set and path identifies a terminal device, 
//    open() shall not cause the terminal device to become 
//    the controlling terminal for the process.
uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY); //Open in non blocking read/write mode
if (uart0_filestream == -1) {     // ERROR - CAN'T OPEN SERIAL PORT
  printf("Error - Unable to open UART. Ensure it is not in use by another application\n");
}

// CONFIGURE THE UART
// The flags (defined in /usr/include/termios.h 
//     - see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html):
// Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600, 
//             B115200, B230400, B460800, B500000, B576000, B921600, 
//             B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, 
//             B3500000, B4000000
// CSIZE:- CS5, CS6, CS7, CS8
// CLOCAL - Ignore modem status lines
// CREAD - Enable receiver
// IGNPAR = Ignore characters with parity errors
// ICRNL - Map CR to NL on input 
//         (Use for ASCII comms where you want to auto correct 
//         end of line characters - don't use for bianry comms!)
// PARENB - Parity enable
// PARODD - Odd parity (else even)
struct termios options;
tcgetattr(uart0_filestream, &options);
options.c_cflag = B9600 | CS8 | CLOCAL | CREAD; //<Set baud rate
options.c_iflag = IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
tcflush(uart0_filestream, TCIFLUSH);

tcsetattr(uart0_filestream, TCSANOW, &options);

코드가 좀 길기는 해도 코멘트를 참고하면 이해하는데 문제는 없을 것이다. 위의 코드는 시리얼 포트를 9600bps, 8 bit data, no parity, non-blocking 모드로 오픈해준다.

시리얼 포트가 오픈되었으면 아래와 같이 데이터를 송수신 할 수 있다.

데이터 전송

//----- TX BYTES -----
unsigned char tx_buffer[20];
unsigned char *p_tx_buffer;

p_tx_buffer = &tx_buffer[0];
*p_tx_buffer++ = 'H';
*p_tx_buffer++ = 'e';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'o';

if (uart0_filestream != -1) {
  int count = write(uart0_filestream, &tx_buffer[0], (p_tx_buffer - &tx_buffer[0])); //Filestream, bytes to write, number of bytes to write
  if (count < 0) {
    printf("UART TX error\n");
  }


}

데이터 수신

//----- CHECK FOR ANY RX BYTES -----
if (uart0_filestream != -1) {
  // Read up to 255 characters from the port if they are there
  unsigned char rx_buffer[256];
  int rx_length = read(uart0_filestream, (void*)rx_buffer, 255); //Filestream, buffer to store in, number of bytes to read (max)
  if (rx_length < 0) {
    //An error occured (will occur if there are no bytes)
  } else if (rx_length == 0) {
    //No data waiting
  } else {
    //Bytes received
    rx_buffer[rx_length] = '\0';
    printf("%i bytes read : %s\n", rx_length, rx_buffer);
  }

}

일반적인 경우 수신된 데이터가 없을 때 read()를 호출하면 데이터가 수신될 때 까지 실행이 멈추게 되지만 여기서는 시리얼포트를  O_NDELAY 플래그를 사용해 non-blocking 모드로 오픈했기 때문에 read()를 호출했을 때 수신된 데이터가 없어도 바로 리턴하기 때문에 코드 내에서 데이터가 수신되기를 기다려야 한다면 while 루프등을 사용해야 한다.

시리얼 포트를 다 사용했다면 포트를 close하면 된다.

// —— CLOSE THE UART —— 
close(uart0_filestream);

시리얼 포트가 동작하는지 확인할 수 있는 가장 쉬운 방법은 Tx와 Rx핀을 서로 연결해 준 다음 프로그램에서 송신한 데이터가 그대로 수신되는지 확인해 보면 된다. (Loopback Test)



2011년 2월 26일 토요일

탈옥하지 않은 아이폰에 시리얼포트 사용하기: HiJack (Add serial port to un-jailbroken iPhone: HiJack)

UMich에서 아주 재미있는 프로젝트가 진행되었다. HiJack이라고 아이폰의 헤드폰 단자에 꼽아 외부 주변기기와 통신을 할 수 있는 디바이스를 만든 것이다.



아이폰의 30핀 독 커넥터에도 시리얼 포트가 있기 때문에 외부 디바이스를 연결할 수 있지만 이 경우 탈옥을 하지 않은 아이폰/터치팟의 경우 애플의 인증칩이 붙어 있어야만 동작하고 관련 자료를 구하는것도 개발자 프로그램에 가입해야만 가능하기 때문에 제약이 많았다.
물론 탈옥을 하고 나면 모든 제한이 사라지고 리눅스에서 시리얼 포트 사용하는것과 동일하게 사용할 수 있게 된다.

하지만 HiJack을 사용하면 탈옥을 하지 않은 순정 아이폰/터치팟에 시리얼포트 뿐 아니고 digital I/O를 제공해주기 때문에 여러가지 외부 디바이스를 손쉽게 아이폰에 인터페이스 할 수 있다.

당연히 지금까지 이런 방식을 사용하지 않았던건 아니다.
이미 위의 사진같이 Square라는 회사에서 아이폰용 신용카드 리더를 만들어 제공하고 있는데 이 역시 기본적으로 동일한 방식을 사용해서 통신을 하는 것이다.

단 차이는 사진의 리더기는 완성된 제품인데 비해 HiJack은 모든 관련자료와 필요한 소스코드까지 완전히 공개되어 있다는 점이다.

그리고 이 회로의 훌륭한 점은 헤드폰 잭은 스테레오라는걸 이용해서 아이폰에서 HiJack으로 데이터 전송은 왼쪽 모노 채널을 통해 보내고 오른쪽 모노 채널로는 지속적으로 22KHz 톤을 보내 HiJack에서는 그 톤은 energy harvesting회로를 통해 자신에게 전원을 공급하는데 사용한다.
약 47%의 변환효율을 보여 7.4mW의 전력을 공급한다.

데이터 전송 속도는 Bell 202 FSK modulation을 사용할 때는 300bps, Manchester encoding된 디지털 신호를 직접 사용하는 경우는 8.82kbps가 된다.

시리얼 포트 뿐 아니고 MSP430의 A/D나 digital I/O신호도 사용할 수 있기 때문에 아래 사진은 HiJack에 EKG모니터를 연결한 경우이다.




ECG Extension for HiJack from Thomas Schmid on Vimeo.



Hijacking Power and Bandwidth from the Mobile Phone's Audio Interface - Integrated Prototype from Thomas Schmid on Vimeo.



Hijacking Power and Bandwidth from the Mobile Phone's Audio Interface from Thomas Schmid on Vimeo.



SoilJack - A Low-Cost Phone Soil Moisture Meter from Thomas Schmid on Vimeo.

회로와 관련 소스는 http://code.google.com/p/hijack-main/ 에서 다운받을 수 있다.

좀 더 자세한 정보와 관련 논문은 프로젝트 홈페이지인 http://eecs.umich.edu/~prabal/projects/hijack/ 를 참조하면 된다.

2010년 6월 15일 화요일

mbed RPC 인터페이스 (RPC interface for mbed)



mbed는 인터페이스 오브젝트에 이름을 부여해주면 텍스트 기반 인터페이스를 통해 제어할 수 있다.

메소드는 url과 유사한 방식으로 호출된다.

/<objectname>/<method> <arg1> <arg2> ...

가장 기본적인 예제이다.

#include "mbed.h"

DigitalOut led(p1, "led");

int main() {
    char result[64];
    
    rpc("/led/write 1", result);
    printf("%s\n", result);
    
    rpc("/led/read", result);
    printf("%s\n", result);
}


Remote Control

mBed를 터미널에 연결하고 시리얼 포트 입력을 기다리도록 하면 시리얼을 통해 직접 명령어를 입력하고 그 결과를 돌려받을 수 있다.

#include "mbed.h"

Serial pc(USBTX, USBRX);

DigitalIn led(p1, "led");
AnalogIn pot(p20, "pot");

int main() {
    char buf[256], outbuf[256];
    while(1) {
        pc.gets(buf, 256);
        rpc(buf, outbuf);
        pc.printf("%s\n", outbuf);
    }
}

터미널이 엔터키가 눌렸을 때 LF(또는 CR+LF)를 보내도록 설정되어 있어야 한다.
 

위의 프로그램이 실행되고 있으면 터미널에서 직접 명령어를 넣어주면 된다.

/led/write 1<return>     LED를 켠다.
/pot/read<return>        아날로그 핀 20의 값을 읽는다.  

Remote Creation of mbed interfaces

RPC인터페이스를 사용하면 원격에서 인터페이스를 만들거나 삭제할 수 있다.


새 인터페이스를 만들려면 mbed에게 만들려고 하는 인터페이스에 대해 알려줘야 한다. 아래 코드는 원격 어플리케이션에서 이런 동작을 할 수 있도록 해 주는 시리얼 어플리케이션 예제이다.

/* RPCSerial - RPC over a serial port transport
 * sford
 *
 * When running, you can send RPC commands to the mbed
 * via the serial port, to create and manipulate objects
 *
 * Example:
 * > "/DigitalOut/new p2\n"
 * > > "objXYZ\n"
 * > "/objXYZ/write 1\n"
 * > "\n"
 * > "/objXYZ/read"
 * > "1\n"
 */
#include "mbed.h"
#include "rpc.h"
Serial pc(USBTX, USBRX);
int main() {
    // setup the classes that can be created dynamically
    Base::add_rpc_class<AnalogIn>();
    Base::add_rpc_class<AnalogOut>();
    Base::add_rpc_class<DigitalIn>();
    Base::add_rpc_class<DigitalOut>();
    Base::add_rpc_class<PwmOut>();
    Base::add_rpc_class<Timer>();
    Base::add_rpc_class<SPI>();
    Base::add_rpc_class<BusOut>();
    Base::add_rpc_class<BusIn>();
    char command[256] = {0};
    char response[256] = {0};
    // receive commands, and send back the responses
    while(1) {
        pc.gets(command, 256);
        rpc(command, response);
        pc.printf("%s\n", response);
    }
}


실행 예제 (볼드체로 된 부분이 직접 입력한 내용이고 이태릭체로 된 부분은 mbed의 응답이다.)

/DigitalOut/new LED1
obj400058B0
/obj400058B0/write 1



/AnalogIn/new p3 volume

volume
/volume/read
0.297
/volume/delete

시리얼 인터페이스 뿐 아니고 mbed에 내장된 웹서버를 사용해 HTTP 프로토콜로 RPC 호출을 할 수도 있다. URL의 페이지 주소가 '/rpc/'로 시작하면 웹 서버가 RPC 리퀘스트로 처리한다.


예를 들어 URL이 'http://mbed-ip-or-hostname/rpc/led1/write+1' 이면 시리얼 터미널에서 '/led1/write 1'을 입력한것과 동일한 동작을 수행한다. (URL주소에서 space는 '+'로 대치)


#include "mbed.h"
#include "HTTPServer.h"
#include "HTTPRPC.h"
#include "HTTPFS.h"
HTTPServer http;
DigitalOut led1(LED1, "led1");
DigitalOut led2(LED2, "led2");
DigitalOut led3(LED3, "led3");
DigitalOut led4(LED4, "led4");
LocalFileSystem local("local");
int main(void) {
    Base::add_rpc_class<AnalogIn>();
    Base::add_rpc_class<AnalogOut>();
    Base::add_rpc_class<DigitalIn>();
    Base::add_rpc_class<DigitalOut>();
    Base::add_rpc_class<PwmOut>();
    Base::add_rpc_class<Timer>();
    Base::add_rpc_class<SPI>();
    Base::add_rpc_class<BusOut>();
    Base::add_rpc_class<BusIn>();
    http.addHandler(new HTTPRPC());
    http.addHandler(new HTTPFileSystemHandler("/", "/local/"));
    http.bind();
    while(1) {
        http.poll();
    }
}



2010년 3월 7일 일요일

DIAMEX DXM 명령어 목록

DIAMEX DXM module은 시리얼 포트를 통해 PC와 통신을 하고 AT명령어 셋을 사용하기 때문에 이미 나와있는 대다수의 OBD-II 소프트웨어와 호환된다. 지원하는 AT명령어 목록은 다음과 같다.
--

DIAMEX DXM command list

COMMAND

Explanation

ATZ

Reboot the controller

ATWS

Same as ATZ but faster

ATI

Identification text is reported

ATD

All parameters are stored in the ground state as after a cold or warm state

ATE0/1

Toggle the serial echo on/off

ATL0/1

Toggle the transmission of the linefeed(L/F)

ATM0/1

Toggle the memory function of the final protocol

ATH0/1

Toggle if the OBD2 header answers and checksum byte shall be displayed

ATBD

Causes the display of the OBD2 receive buffer

ATB

Display of the OBD2 reception buffer

ATSRxx

Input of the RX ECU OBD2 filter address for OBD2 responses

ATN

Display of the current protocol used as HEX value F0..F9

  • F0 – no active protocol  

  • F1 – PWM protocl 

  • F2 – VPWM protocol 

  • F3 – ISO9141 protocol 

  • F4 – KWP2000 protocol 

  • F5 – KWP2000 protocol 

  • F6 – CAN 11-bit ID, 500 kBaud 

  • F7 – CAN 29-bit ID, 500 kBaud 

  • F8 – CAN 11-bit ID, 250 kBaud 

  • F9 – CAN 29-bit ID, 250 kBaud 

ATDP

Display of the currently used protocol in plaintext

  • NOT CONNECTED 

  • SAE J1850/PWM 

  • SAE J1850/VPWM 

  • ISO9141-2 

  • ISO14230-4, KWP2000 (5 BAUD Init) 

  • ISO14230-4, KWP2000 (Fast Init) 

  • ISO15765-4, CAN(11/500) 

  • ISO15765-4, CAN(29/500) 

  • ISO15765-4, CAN(11/250) 

  • ISO15765-4, CAN(29/250) 

ATK

Display the current keywords on ISO9141 and KWP2000

ATKW0/1,

For a slow, init keywords are distinguished between protocol 3 (ISO9141) and protocol 4 (KWP2000). This automatic detection can be disabled with ATKW0

ATP[A]x

Manual setting of the current protocol or the automatic protocol search

  • ATP1 – PWM 

  • ATP2 – VPWM 

  • APT3 – ISO9141-2 

  • ATP4 – KWP2000 5 BAUD Init 

  • ATP5 – KWP2000 Fast Init 

  • ATP6 – CAN 11/500 

  • ATP7 – CAN 29/500 

  • ATP8 – CAN 11/250 

  • ATP9 – CAN 29/250 

ATV

Overview of all the modifiable parameters of the DXM1 are displayed

ATSBx

Set baud rate of serial interface

  • ATSB0 – 9600 Baud (Standard) 

  • ATSB1 – 19200 Baud 

  • ATSB2 – 38400 Baud 

  • ATSB3 – 57600 Baud 

  • ATSB4 – 115200 Baud 

  • ATSB5 – 125000 Baud 

  • ATSB6 – 250000 Baud 

ATSHxxyyzz

Manual setting of the header bytes for ISO9141, KWP2000, PWM and VPWM protocol

  • xx = priority/type-byte 

  • yy = target-address 

  • zz = source-address 

ATWMxxyyzzaa[bb][cc]

Manual setting of the wakeup message bytes for ISO9141 and KWP2000

  • xx = priority/type-byte (with length indication in KWP) 

  • yy = target-address 

  • zz = source-address 

  • aa, bb, cc = command bytes 1~3 

ATSWxx

The length of time between automatic wakeup commands in existing ISO9141 and KWP2000 can be set

ATCA0/1

The automatic formatting of the transmitted and received CAN data can be switched on/off

ATCC0/1

Multi-frame answers have to be sent flow control messages from the tester, which indicate the controller, that following packages have to be accepted

ATCDxx

Flow control data packages which has to be sent in multi frame responses, contain beside the status byte (FS), a block size byte (BS) and also a byte for the duration (ST), which have to be added between the following response packages

ATCIxxx/xxxxxxxx

CAN-ID which has to be sent, is set with this command

  • 11-bit ID – 7DF (default) 

  • 29-bit ID – 18 DD 33 F1 (default) 

ATCFxxx/xxxxxxxx

Set CAN RX-filter

  • 11-bit ID – 7E8 (default) 

  • 29-bit ID – 18 DA F1 00 (default) 

ATCMxxx/xxxxxxxx

Set CAN RX-mask

  • 11-bit ID – 7F8 (default) 

  • 29-bit ID – 1F FF FF 00 (default) 

AT!00

Output of the serial number of the DXM controller

AT!01

Output of the controller type and the BIOS version number

AT!10

Mesaurement of 12-volt vehicle power



2009년 10월 24일 토요일

Airlink AR670W serial port 및 dd-wrt flashing

저렴한 가격에 300Mbps 802.11n을 지원하는 유무선 공유기인 Airlink의 AR670W를 구입하였다.
물론 DD-WRT 개조를 염두에 두고 호환목록 리스트를 확인 한 다음에 결정한 모델이다. 현재 가장 최신버젼의 dd-wrt는 v24preSP2(build 13064)인데 운 좋게도 이 버젼부터 AR670W를 지원한다.


일단 제품을 받은 다음 케이스를 분해 해 보았다.


RALink칩셋인 RT2880 + RT2820을 사용하고 32MB의 메모리를 가지고 있다.
또한 사진에서 볼 수 있는것처럼 JTAG port와 serial port가 제공되고 serial port는 사용하기 좋게 미리 header까지 땜질이 되어 있었다.


약간의 검색을 해 본 결과 시리얼 포트의 핀 배치는 위의 사진과 같고 시리얼 포트 파라미터는 57600bps, no parity, 8 bit, 1 stop bit를 사용하면 된다.

간단하게 접속 케이블을 만들어 FT232 모듈에 연결하고 공유기 전원을 넣으니 바로 부팅 시퀀스를 볼 수 있었다. 이 제품 역시 리눅스를 사용하고 있다.

AR670W booting sequenc


DD-WRT 펌웨어로 교체도 매우 쉽게 가능하다. 호환 디바이스 목록에서 AR670W를 입력하면 2개의 파일이 나온다.

Webflash image용인 ar670w-ddwrt-webflash.bin과 Special image for initial flashing용인 airlink-factory-webflash.bin이다. 일단 dd-wrt로 변경된 경우에는 첫번째 파일을 사용하면 되지만 아직 원래 ar670w용 펌웨어를 가지고 있는 경우에 dd-wrt로 바꾸는 경우는 두번째 파일을 받아 플래슁을 해 줘야만 한다.


웹 브라우져에서 공유기 관리자 화면으로 들어가서 저기에 airlink-factory-webflash.bin을 선택해주고 Apply 버튼을 눌러주면 된다.


2008년 6월 23일 월요일

Serial Proxy - 네트웍을 통해서 시리얼 포트를 사용하기

Serproxy (Serial Proxy)는 시리얼 포트의 입출력을 TCP/IP 네트웍을 통해 리다이렉션 시켜주는 멀티쓰레드 프락시 소프트웨어이다. 작은 임베디드 보드의 경우 시리얼 포트만 가지고 있고 tcp/ip 스택을 가지고 있지 않아서 네트웍을 통해 연결을 할 수 없는 경우가 많다. 이런 경우 serproxy를 사용하면 원격지에 있는 디바이스를 네트웍을 통해 제어할 수 있게 된다.

그 이외에도 플래쉬나 다른 프로그래밍 언어로 사용자 인터페이스를 만드는 경우 해당 언어에서 시리얼 포트를 제어하는 라이브러리를 제공해주지 않으면 시리얼 포트를 사용할 수가 없지만 serproxy를 사용하면 소켓 프로그래밍 인터페이스를 사용해서 시리얼 포트로 데이터를 주고 받을 수 있다.


200806222356.jpg

(a) 시리얼 포트를 직접 억세스하는 경우


200806222356.jpg

(b) Serial proxy를 사용하는 경우

위의 그림 (b)에서는 serproxy를 실행하는 컴퓨터와 그 시리얼 포트를 사용하는 컴퓨터를 따로 그려 놨지만 한 컴퓨터에서 serproxy를 실행하고 같은 컴퓨터에서 소켓 프로그램으로 시리얼 포트를 억세스 할 수도 있다. (제어 프로그램을 플래시로 만드는 경우 경우 플래시에서 시리얼 포트를 직접 억세스 할 수 없기 때문에 이런 방법을 사용해야 한다. 이 경우 destination ip: localhost, port: cfg파일에 설정한 포트번호로 억세스 하면 된다.)

여기서 소스 및 윈도우용 바이너리 파일을 다운받을 수 있다.

맥용 바이너리 파일은 아래에서 다운받으면 된다.


압축을 열어보면 serproxy와 serproxy.cfg 가 있는데 serproxy.cfg는 /usr/local/etc에 serproxy는 /usr/local/bin에 복사해주고 자신의 환경에 맞게 serproxy.cfg를 바꿔주면 된다.


# 시리얼 포트에서 오는 뉴라인('\n')을 nils('\00') 으로 변환

# 플래시의 경우 끝에 nils가 오지 않으면 앞부분을 해석하지 않기 때문에 이 기능이 필요하다. true (e.g. 플래시를 사용하는 경우 or false

newlines_to_nils=true

# 사용할 시리얼 포트, 여기서는 2개를 사용하는 경우, 각각 1, 2가 된다.

comm_ports=1,2

# 디폴트 설정

comm_baud=19200

comm_databits=8

comm_stopbits=1

comm_parity=none

# 아이들 타임아웃

timeout=300

# 포트 맵핑 설정, 즉 시리얼 포트 1은 TCP포트 5531을 통해, 시리얼 포트 2는 TCP포트 5532를 통해 사용할 수 있음

net_port1=5331

net_port2=5332

# 각 시리얼 포트 디바이스 이름

serial_device1=/dev/tty.usbserial

serial_device2=/dev/tty.usbserial-3B1

2008년 6월 9일 월요일

Mac OS X에서 시리얼 터미널 프로그램 (Serial Terminal Emulator in Mac OS X)

사용자 삽입 이미지


Embedded환경에 익숙한 사람이라면 가장 중요한 툴중에 하나가 시리얼 포트이다. Mac OS X에는 telnet, ssh 프로토콜을 지원하는 좋은 네트웍 터미널 프로그램이 많은데 비해 시리얼 터미널 프로그램을 찾아보기가 쉽지 않다. 시리얼 포트를 자유롭게 사용할 수 없다면 아무리 맥에서 크로스 컴파일러로 hex파일을 만들어도 다운할 수도 없고 embedded board의 콘솔 출력을 보기 힘들게 된다. 그래서 맥에서 시리얼 포트를 사용하는 방법을 여기에 정리해 보려고 한다.

* 잘 알다시피 OS X가 발표된 이후에 나온 하드웨어들에는 시리얼 포트가 장착되어 있지 않다. 시리얼 포트를 사용하려면 USB to RS-232 컨버터를 구입해야 한다. 구입시 따라오는 디바이스 드라이버를 설치한 다음에 컨버터를 연결해주면 /dev 디렉토리에 /dev/tty.usbserial, /dev/cu.usbserial 같은디바이스 파일이 생성된다.

1. 터미널 프로그램으로 'screen' 을 사용
Mac OS X에 기본으로 포함되어 있는 screen을 시리얼 터미널 프로그램으로 사용할 수 있다. 원래는 가상 터미널을 만들어주는 프로그램이지만 시리얼 디바이스에 연결된 가상 터미널도 만들 수 있다. 먼저 mac os x 의 terminal이나 iTerm같은 프로그램을 실행해서 커맨드 프롬프트에서

$ screen <디바이스 이름> <전송속도>

의 형태로 사용하면 된다. 자세한 옵션이나 사용방법은 man page을 참조하면 된다. ($ man screen)
시리얼 터미널에서 빠져나오려면 'ctrl-a, ctrl-\'를 순서대로 눌러주면 된다.

2. kermit을 사용

ftp://kermit.columbia.edu/kermit/public_html/ckermit.html

위의 링크에서 소스를 받아 컴파일을 하려고 하면 맥은 UUCP lockfile (/var/spool/lock)을 지원하지 않기 때문에 빌드에서 에러가 발생한다. 이 경우 KFLAGS=-DNOUUCP 옵션을 붙여서 컴파일 해 주면 된다.

$ make macosx10.4 KFLAGS=-DNOUUCP

이렇게 빌드해 준 바이너리를 현재 OS X 10.5.3에서도 문제없이 사용하고 있다. 단 UUCP lockfile을 사용하지 않기 때문에 시리얼 포트를 한번에 한 인스턴스의 kermit만 open하도록 강제하지 못하지만 맥을 동시에 여러명이 사용하지 않는 이상 큰 문제는 없다.
빌드 및 설치가 끝난 다음에 시리얼 포트에 연결하려면 kermit을 실행시킨 다음 아래의 명령을 사용하면 된다.

c-kermit> set modem type none     ; 널모뎀인 경우 모뎀 타입을 'none'으로 해 준다.
c-kermit> set carrier-watch off   ; 널모뎀이기 때문에 별도의 캐리어가 없으므로 off
c-kermit> port /dev/tty.USBSERIAL ; 자신이 사용하는 usb to rs-232 converter 디바이스
c-kermit> flow none               ; flow control, default는 rts/cts이다.
c-kermit> speed 57600             ; 통신 속도(bps)
c-kermit> connect                 ; 연결

일단 연결된 상태에서 명령어 프롬프트(c-kermit>) 으로 빠져 나오려면 'CTRL-\ 다음에 c'를 누르면 된다. 연결을 끊으려면 close 명령어를 사용한다.
사용하기에는 c-kermit이 조금 더 복잡하지만 그 이상으로 막강한 기능을 가지고 있기 때문에 훨씬 더 유용하다.

* Mac OS X용 GUI 시리얼 터미널 프로그램에 대해 추가된 글
맥 OS X용 시리얼 터미널 CoolTerm (CoolTerm - Serial Terminal Software for Mac OS X)