2014年3月2日 星期日

Raspberry Pi 整合 GPS 模組教學

好一陣子沒有在玩 Raspberry Pi 了,由於網友詢問這類問題剛好手上有GPS模組所以找了空檔寫了這篇希望能有所幫助。
一般GPS大概都是透過非同步式串列介面(UART)作為訊號傳遞連結,模組與Raspberry Pi連結就是透過高低電位的TTL方式使用UART介面來傳遞,通常運用到模組上的RX,TX 兩條訊號線及VCC/GND (這裡的VCC是供電給GPS模組使用的)。
模組上你可能會看到還有VBAT這是外接電池使用或者每家開發商會有不同的定義其他腳位,這個部分就得要看所買到的GPS模組Datasheet了。

至於GPS模組中還要注意的是協議部分,常見的GPS模組內建協議包括NMEA-0183SiRF binary、RTCM SC-104等格式,這些協議格是可以透過AT命令進行切換,本篇文章則以常見的NMEA為主,好處是讀取道的資訊是一般的明碼,我們取來應用比較方便。

其他關於GPS模組部分還有是近兩年流行的雙衛星系統接收。所謂雙衛星系統指的是美國的GPS (全球定位系統)及蘇聯的GLONASS(全球導航衛星系統),其相關資料這裡就不多敘述有興趣的詳見 "淺談GPS/ GLONASS雙星定位系統" 網頁。至於雙衛星系統最主要的優點是定位迅速冷啟動大約在30秒即可定位。

實作Raspberry Pi 整合 GPS 模組有兩種方式,一種是透過TTL方式直接跟IO接腳的第8腳UART TX及第10腳UART RX連結(方案一),另外就是GPS模組透過 USB to TTL Adapter Cable連接到Raspberry Pi 的 USB上面(方案二)。詳細接線圖如下:
方案一

方案二


實作
上述兩種接線方法,當Raspberry Pi 開機完成進入Linux系統,在Linux系統的差別在於裝置名稱而已,也就是說程式部分只要連結到不同的/dev下的裝置。

這裡需要記住的是:
1.如果使用的方法是透過IO接腳的第8腳及第10腳連結GPS模組的話(方案一),程式直接對 /dev/ttyAMA0 存取。
2.如果使用的方法是透過 USB to TTL Adapter Cable連接到Raspberry Pi 的 USB上面(方案二),程式直接對 /dev/ttyUSB0 存取。
3.傳輸的鮑率(Baud Rate) ,一般會用4800或9600設定錯誤的話收到的資料會是亂碼。

接著分為兩種語言實作:
1. Python
在寫程式的前置動作必須先安裝 python 的 serial 函式庫,執行下列指令:

sudo apt-get install python-serial

接著用編輯器編輯一個檔案名稱為 gps.py 的程式,其內容如下:


import serial

def getdata(port):
# open the serial port
    port.open()
# check that the port is open
    if port.isOpen():
# read 16 lines
        line = []
        for i in range(1,16):
            line.append(port.readline())
# close the serial port
    port.close()
# discard the first line (sometimes it contains rubbish, so just always discard it)
    del line[0]
# return the list of lines
    return line

def outputdata(data):
# print the list of lines
    for i in range(0,len(data)):
        print data[i]

def initialise():
# initialise serial port settings
    Port = serial.Serial()
    Port.baudrate = 9600              //鮑率(Baud Rate)
    Port.port = '/dev/ttyAMA0'       //如接USB的話改成dev/ttyUSB0
    Port.xonxoff = 1
# return the port as an object we can use
    return Port

# main program starts here
sPort = initialise()
data = getdata(sPort)
outputdata(data)
# end

執行結果:
使用指令:
sudo python gps.py
結果如下:

2. Java
在寫程式的前置動作必須先安裝 Java 的 serial 函式庫,執行下列指令:

sudo apt-get install librxtx-java

sudo ln -s /dev/ttyAMA0 /dev/ttyS88  
執行這個指令是因為 Java 的 serial 函式庫不會找不到/dev/ttyAMA0 (見下圖),必須使用 /dev/ttySXX的格式才會抓到裝置,如果是用USB連接的方案二方式這指令可以不用執行。

接著用編輯器編輯一個檔案名稱為 SerialComm.java 的程式,其內容如下:

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class SerialComm {

  public SerialComm() {
    super();
  }

  void connect( String portName ) throws Exception {
    CommPortIdentifier portIdentifier = CommPortIdentifier
        .getPortIdentifier( portName );
    if( portIdentifier.isCurrentlyOwned() ) {
      System.out.println( "Error: Port is currently in use" );
    } else {
      int timeout = 3000;
      CommPort commPort = portIdentifier.open( this.getClass().getName(), timeout );

      if( commPort instanceof SerialPort ) {
        SerialPort serialPort = ( SerialPort )commPort;
        serialPort.setSerialPortParams( 9600, //鮑率(Baud Rate)
                                        SerialPort.DATABITS_8,
                                        SerialPort.STOPBITS_1,
                                        SerialPort.PARITY_NONE );

        byte[] buffer = new byte[ 82 ];
        int len = -1;
        try {
          while( ( len = serialPort.getInputStream().read(buffer) ) > -1 ) {
             System.out.print( new String( buffer, 0, len ) );
          }
        } catch( IOException e ) {
          e.printStackTrace();
        }

      } else {
        System.out.println( "Error: Only serial ports are handled by this example." );
      }
    }
  }

  public static void main( String[] args ) {
    try {
      ( new SerialComm() ).connect( "/dev/ttyS88" ); //如接USB的話改成dev/ttyUSB0
    } catch( Exception e ) {
      e.printStackTrace();
    }
  }
}


用下列指令進行編譯:
 javac -cp /usr/share/java/RXTXcomm.jar:. SerialComm.java 


執行結果:
使用指令:
sudo java -Djava.library.path=".:/usr/lib/jni/" -cp /usr/share/java/RXTXcomm.jar:. SerialComm
結果如下:

後記:
本篇文章使用連接方式採用的是方案一,稍微測試了一下Python與Java發現到還是有些不穩,例如Python程式經常遇到下圖錯誤訊息:

而Java也好不到哪去,會出現java.io.IOException: Input/output error in nativeavailable ,問題看來應該是 /usr/lib/jni/librxtxSerial-2.2pre1.so 網路針對這部分找了一個晚上似乎也沒有一個一勞永逸的解決方法。

由於目前比較沒有時間來除錯,所以先跟部落格的朋友說聲抱歉暫時到此,待有空再找找看有沒有解決方式,要不可能就直接寫C問題會少點應該會好些吧!

==============延伸閱讀=====================
1. Raspberry Pi 第一次接觸
http://cheng-min-i-taiwan.blogspot.tw/2013/02/raspberry-pi.html

2.Raspberry Pi 網路設定
http://cheng-min-i-taiwan.blogspot.tw/2013/02/raspberry-pi_23.html

3.Raspberry Pi 應用之Windows檔案伺服器
http://cheng-min-i-taiwan.blogspot.tw/2013/02/raspberry-pi-windows.html

4.Raspberry Pi 應用之DLNA影音伺服器
http://cheng-min-i-taiwan.blogspot.tw/2013/02/raspberry-pi-dlna.html

5.Raspberry Pi 硬體控制-- Python 語言篇
http://cheng-min-i-taiwan.blogspot.tw/2013/04/raspberry-pi-python.html

6.Raspberry Pi 硬體控制-- C 語言篇
http://cheng-min-i-taiwan.blogspot.tw/2013/04/raspberry-pi-c.html

7.Raspberry Pi 2 Model B 使用心得
http://www.cheng-min-i-taiwan.blogspot.tw/2015/02/raspberry-pi-2-model-b.html

8.Raspberry Pi 藍牙4.0應用之iBeacon 發射器
http://www.cheng-min-i-taiwan.blogspot.tw/2015/03/raspberry-pi-40ibeacon.html

9.Raspberry Pi安裝MQTT之應用 -- Android訊息推播
http://www.cheng-min-i-taiwan.blogspot.tw/2015/03/raspberry-pimqtt-android.html

10. Raspberry Pi安裝MQTT之IoT應用 -- Android示範
http://cheng-min-i-taiwan.blogspot.tw/2015/03/raspberry-pimqttiot-android.html#more

13 則留言:

  1. 你好,想請問一下~只要接上GPS Module就可以進行定位動作嗎?
    還是說需要3G或Wifi其他網路連線來配合?

    謝謝!

    回覆刪除
    回覆
    1. 對的!GPS模組就可以進行定位了。

      刪除
  2. 想再問一下~不穩定的原因是出自於gps module本身
    還是說使用的語言的問題?

    最近有在想能不能應用在防竊上面..XD

    回覆刪除
    回覆
    1. 1.不穩是出現在程式上,主要是沒有時間可以Debug...改善空間很大! 文章中GPS模組已經是雙衛星系統,定位很快也準確所以不是GPS問題。

      2.防竊當然可行~但整體而言RPI只能接有線網路,無限或3G可能要透過USB,接著板子大小跟信用卡差不多....建議可以做出雛形後再評估會比較妥當 ^____^

      刪除
  3. 您好
    請問您使用的GPS 模組是哪一套
    想參考一下,購買來做測試

    主要試想要做速度偵測器,但不希望使用輪圈式的
    目的是為了安裝方便,且減少佈線

    麻煩提供相關資訊了
    謝謝

    回覆刪除
    回覆
    1. 只要是RXTX的GPS模組且輸出為"NMEA標準格式"都可以使用。
      文章測試用的模組是U-blox GPS模組,拍賣網購得。露天搜尋一下比較貴的是雙系統衛星系統,比較便宜的是GPS衛星系統,購買在按照需求確認。

      刪除
    2. 謝謝您提供的參考資訊

      我們會再評估看看計算速度利用 雙衛星的效果比較好
      還是利用慣性感測器(G Sensor)的效果比較好

      謝謝 ^^

      刪除
  4. 你好我想請問一下GPS定位只有顯示數值,然後我有沒有方法可以利用地圖看出目前所顯示的數值?

    回覆刪除
    回覆
    1. 可以整合Google Maps APIs
      https://developers.google.com/maps/

      刪除
    2. 作者已經移除這則留言。

      刪除
  5. 你好 請問一下 就是程式執行後顯示那些數值,我是否可以利用地圖來看出我所顯示的位置數值?

    回覆刪除
  6. 您好,我使用RPI3 並使用USB型的GPS 請問找不到 dev/ttyUSB0 該如何處理?

    回覆刪除