2015年1月13日 星期二

Raspberry Pi 連接 Serial Port 週邊裝置 (以 pi4j 連接 GPS 開發板為例)

VK2525 GPS開發板 (露天淘寶都買的到,需另外加購GPS天線)
Raspberry Pi 上需要修改預設的設定檔,原來 GPIO 上的 RX/TX 腳位被拿來做 Serial 連接 Console 用途,故需要將設定拿掉,GPIO 的 RX/TX 才可接其它 Serial 的週邊。

ssh 進入 Raspberry Pi,
1. sudo vi /boot/cmdline.txt
將檔案內容
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
修改為
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait 將 "console=ttyAMA0,115200" 拿掉

2. sudo vi /etc/inittab
將 "T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100註解掉
## T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

依 VK2525 GPS 開發板規格書,使用 9600, N, 8, 1 的連接參數開啟 GPIO RX/TX 接腳的 Serial Port,對應 device file handle 為 /dev/ttyAMA0
我習慣用 java,故透過 pi4j library 連接。程式如下:

import com.pi4j.io.serial.Serial;
import com.pi4j.io.serial.SerialDataEvent;
import com.pi4j.io.serial.SerialDataListener;
import com.pi4j.io.serial.SerialFactory;
import com.pi4j.io.serial.SerialPortException;

public class GPSCollector {

    public static void main(String args[]) throws InterruptedException {

        System.out.println("<--pi4j--> Serial Communication Example ... started.");
        System.out.println(" ... connect using settings: 9600, N, 8, 1.");
        System.out.println(" ... data received on serial port should be displayed below.");

        // create an instance of the serial communications class
        final Serial serial = SerialFactory.createInstance();

        // create and register the serial data listener
        serial.addListener(new SerialDataListener() {
            @Override
            public void dataReceived(SerialDataEvent event) {
                // print out the data received to the console
                System.out.print(event.getData());
            }
        });

        try {
            // open the default serial port provided on the GPIO header
            serial.open("/dev/ttyAMA0", 9600);
        }
        catch(SerialPortException ex) {
            System.out.println(" ==>> SERIAL SETUP FAILED : " + ex.getMessage());
            ex.printStackTrace();
            return;
        }
    }
}


於 Raspberry Pi 執行程式後,若一切順利,開發板的 GPS 訊息開始源源不絕的流進來。只要有資料進來,SerialDataListener 的 dataRecieved() 就會被呼叫。event.getData() 可以取到流進來的字串。

GPS訊息為 NMEA0183 標準規格,如下,其中GPGGA為定位資料。緯度格式為 ddmm.mmmm,經度格式為 dddmm.mmmm
$GPVTG,35.74,T,,M,0.00,N,0.0,K,A*38
$GPGGA,165932.000,2410.4218,N,12041.1728,E,1,04,2.8,166.2,M,16.0,M,,0000*5E
$GPRMC,165932.000,A,2410.4218,N,12041.1728,E,0.00,35.74,130115,,,A*54
$GPVTG,35.74,T,,M,0.00,N,0.0,K,A*38
$GPGGA,165933.000,2410.4218,N,12041.1728,E,1,05,2.6,166.2,M,16.0,M,,0000*50
$GPRMC,165933.000,A,2410.4218,N,12041.1728,E,0.00,35.74,130115,,,A*55
$GPVTG,35.74,T,,M,0.00,N,0.0,K,A*38
$GPGGA,165934.000,2410.4218,N,12041.1728,E,1,05,2.6,166.2,M,16.0,M,,0000*57
$GPRMC,165934.000,A,2410.4218,N,12041.1728,E,0.00,35.74,130115,,,A*52

ddmm.mmmm 要轉成常用的 dd.dddd:
m 除以 60 可以換算成 d
例如,緯度資料 2410.4218,經度資料 12041.1728 :
緯度:  10.4218 / 60 = 0.1737 ,再加 dd 的 24 = 24.1737
經度:  41.1728 / 60 = 0.6862 ,再加 ddd 的 120 = 120.6862
所以得到座標為: 24.1747, 120.6862 (map)

參考資料:
1. RPi Serial Connection: http://elinux.org/RPi_Serial_Connection
2. VK2525 通訊規格: http://wenku.baidu.com/view/ad213be1856a561252d36f0a.html
3. Serial Communication Example using Pi4J: http://pi4j.com/example/serial.html 
4. Java Embedded - 從 Raspberry Pi 開始 : http://www.codedata.com.tw/java/java-embedded-getting-started-from-raspberry-pi/

沒有留言: