2015/03/20

LinkIt ONE:GPS簡單試用

這一篇要試著印出GPS定位資訊,然後拿出GPS資料中的時間,設定給LDateTime。

首先裝上GPS,如下圖,板子上天線孔旁都有標示,應該不會接錯。
然後是程式碼,取自LinkIt ONE開發者手冊中的範例,稍微修改。

#include <LGPS.h>
#define BAUDRATE 19200

gpsSentenceInfoStruct info; // 儲存GPS資料
// 輔助函式,抓出資料的下一個項目
const char *nextToken(const char *src, char *buf){
  int i = 0;
  while(src[i] != 0 && src[i] != ',')
    i++;

  if(buf){
    strncpy(buf, src, i);
    buf[i] = 0;
  }

  if(src[i]){
    i++;
  }
  return src+i;  

// 解析資料,印出想要的東西
void printGPGGA(const char *str)
{
  const char *p = str;
  char t[10];
  int th, tm, ts;
  char latitude[20];
  char ns[2];
  char longitude[20];
  char ew[2];
  char fixq[2];
  char n_satellite[3];
  
  p = nextToken(p, 0);      // GGA
  p = nextToken(p, t);      // Time
  th = (t[0]-'0') * 10 + (t[1]-'0');
  tm = (t[2]-'0') * 10 + (t[3]-'0');
  ts = (t[4]-'0') * 10 + (t[5]-'0');
  p = nextToken(p, latitude);  // Latitude
  p = nextToken(p, ns);      // N, S
  p = nextToken(p, longitude); // Longitude
  p = nextToken(p, ew);      // E, W
  p = nextToken(p, fixq);       // fix quality
  p = nextToken(p, n_satellite);       // number of satellites
  
  if(fixq[0] == '1'){
    Serial.print("UTC time: ");
    Serial.print(th); Serial.print(":");
    Serial.print(tm); Serial.print(":");
    Serial.println(ts);
    Serial.print("Satellite(s): ");
    Serial.println(atoi(n_satellite));
    Serial.print("Latitude: ");
    Serial.print(ns);
    Serial.println(latitude);
    Serial.print("Longitude: ");
    Serial.print(ew);
    Serial.println(longitude);
  }
  else{
    Serial.println("GPS is not fixed yet.");    
  }


void setup(){
  Serial.begin(BAUDRATE);
  LGPS.powerOn();
  Serial.println("GPS power on...waiting");
  delay(3000);
}

void loop(){
  Serial.println("-------------------");
  LGPS.getData(&info);
  Serial.println((char *)info.GPGGA);
  printGPGGA((const char *)info.GPGGA);
 
  delay(10000);
}


會有很多資料,包括GPGGA(全球定位系統資料)、GPGSA(GPS精準度及可使用的衛星資訊)、GPGSV(可連結的衛星詳細資訊)、GPRMC(簡易的GPS位置資訊)等等,此篇只處理GPGGA,也只印出其中某部分。

輸出樣子如下,有UTC時間,追蹤到幾個衛星,緯度與經度。
LinkIt ONE API中有個LDateTime,只要有電源,它就會不停跳動,但必須先給它一個起跳的日期時間。而剛剛抓到的GPS資料中有UTC時間,所以把程式碼稍稍改寫如下:

#include <LGPS.h>
#include <LDateTime.h>
#define BAUDRATE 19200

gpsSentenceInfoStruct info;

const char *nextToken(const char *src, char *buf){
//...省略...
}

void printGPGGA(const char *str)
{
  //...省略...
  char n_satellite[3];
  datetimeInfo dt;
  LDateTime.setTime(&dt);
  
  p = nextToken(p, 0);      // GGA
  p = nextToken(p, t);      // Time
  th = (t[0]-'0') * 10 + (t[1]-'0');
  tm = (t[2]-'0') * 10 + (t[3]-'0');
  ts = (t[4]-'0') * 10 + (t[5]-'0');
  dt.hour = th;
  dt.min = tm;
  dt.sec = ts;
  LDateTime.setTime(&dt); // 此處只設定時間
 
  //...省略...
}
void setup(){
//...省略...}
void doit(){
  LGPS.getData(&info);
  Serial.println((char *)info.GPGGA);
  printGPGGA((const char *)info.GPGGA);
}
void loop(){
  if(Serial.available()){
    char d = Serial.read();
    switch(d){
      case 's': // 若收到's',抓取GPS資料,並設定時間
        doit();
      break;
      case 'r':{ // 若收到'r',從LDateTime拿到時間並印出
        datetimeInfo dt;
        LDateTime.getTime(&dt);
        Serial.print(dt.hour); Serial.print(":");
        Serial.print(dt.min); Serial.print(":");
        Serial.println(dt.sec);
      }
      break;
    }
  }
}

輸出如下:
不知道為什麼,LDateTime的時間會落後於GPS的時間,而且似乎越差越遠;但程式中明明每次抓取GPS資料時,都會再次設定,卻好像無作用似的,真奇怪。

28 comments:

  1. Anonymous7/8/15 02:10

    不知道為何,我定位出來差了44KM
    請問有大大有相同經驗嗎?

    ReplyDelete
    Replies
    1. 等了多久?
      確定fix是1嗎?

      Delete
    2. Anonymous7/8/15 14:50

      確定 頭上衛星數可以到17個
      然後人在基隆定位到蘆洲...

      Delete
    3. 嗯,不知。
      建議到官方論壇問問看。

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. 請問 GPS 的範例程式要在哪找呢 都是英文看不懂...
      另外我想請問 model 跟debug 是插在哪呢?
      那範例程式是複製下來就能用了嗎

      Delete
    2. 英文很重要。

      model跟debug?什麼地方的?

      這篇並未自行撰寫範例程式,
      而是取自LinkIt ONE開發者手冊中的範例,稍微修改。

      Delete
    3. 我是直接使用您的程式 上面那個可用
      但顯示出來衛星數是0
      下面那個不知為何有錯誤

      後來我直接用 上面file
      Examples 裡的範例檔 也是顯示 衛星數0
      請問我是有什麼環節出錯了嗎

      Delete
    4. > 衛星數是0
      得到fix了嗎?有拿到戶外嗎?等得夠久了嗎?

      > 下面那個不知為何有錯誤
      什麼錯誤?

      > 我是有什麼環節出錯了嗎
      請詳述。

      Delete
    5. 這個是我用examples的範例檔 出來的結果

      UTC timer 0- 1- 0
      latitude = 8960.0000, longitude = 0.0000
      satellites number = 0
      LGPS loop
      $GPGGA,000102.000,8960.0000,N,00000.0000,E,0,0,,137.0,M,13.0,M,,*40

      這是在您的文章中比較下面的那一篇的程式碼 我按verify出現的錯誤
      GPS.ino: In function 'void printGPGGA(const char*)':
      GPS.ino:18:3: error: 'p' was not declared in this scope
      GPS.ino:19:20: error: 't' was not declared in this scope
      GPS.ino:20:3: error: 'th' was not declared in this scope
      GPS.ino:21:3: error: 'tm' was not declared in this scope
      GPS.ino:22:3: error: 'ts' was not declared in this scope
      GPS.ino: In function 'void setup()':
      GPS.ino:32:12: error: a function-definition is not allowed here before '{' token
      GPS.ino:37:12: error: a function-definition is not allowed here before '{' token
      GPS.ino:54:1: error: expected '}' at end of input

      而在您的文章中比較上面的那一篇的程式碼 執行的結果

      $GPGGA,000045.000,8960.0000,N,00000.0000,E,0,0,,137.0,M,13.0,M,,*42

      GPS is not fixed yet.


      我有插電池 拿到窗邊試 中間的那顆燈有閃紅燈 想說應該有抓到
      插回電腦試 還是一樣

      另外 如果燒程式事先按 verify 再按上傳麻 要調到debug的埠
      如果要看東西 就要調到另一埠 我應該沒做錯吧

      Delete
    6. > 文章中比較下面的那一篇的程式碼 我按verify出現的錯誤
      因為上下兩份程式碼,很多地方重複,所以我省略掉了。
      在下份程式碼裡,有很多「//...省略...」的部份,請參看上份程式碼補上。

      > 比較上面的那一篇的程式碼 執行的結果 GPS is not fixed yet.
      沒有fix,代表LinkIt ONE的GPS模組尚未或無法成功定位。

      > 中間的那顆燈有閃紅燈
      我這篇裡的程式碼,並沒有控制LED燈。

      > 拿到窗邊試
      可能還不夠久,第一次定位,說不定需要30分鐘、甚至以上。
      說不定拿到窗邊還不夠,要拿到街上。

      > 調到debug的埠
      若是燒錄程式時,應使用Debug那一個,而進行序列埠傳輸時,應使用Modem那一個。

      Delete
  3. 你好,我將GPS接上後,
    -------------------
    $GPGGA,000005.000,8960.0000,N,00000.0000,E,0,0,,137.0,M,13.0,M,,*46

    GPS is not fixed yet.

    只會持續顯示GPS is not fixed yet.如上
    不知道是甚麼問題....

    ReplyDelete
    Replies
    1. 室內收不到GSP,請拿到室外。

      第一次啟動,需要很長的時間,說不定要30分鐘以上,才會得到fix。

      Delete
    2. This comment has been removed by the author.

      Delete
    3. 所以我啟動後先將linkit放著試試看嗎?
      我這裡不方便拿到室外...手機GPS有訊號的地方應該就可以吧??

      Delete
    4. > 啟動後先將linkit放著試試看嗎?
      對。

      > 手機GPS有訊號的地方應該就可以吧
      照理說是如此。

      Delete
  4. This comment has been removed by the author.

    ReplyDelete
  5. Anonymous15/8/16 15:49

    大大您好:
    下載LGPS.h的連結已經頁面不見了,
    可在提供一次嗎?

    ReplyDelete
    Replies
    1. LGPS.h是Linkit ONE SDK提供的。

      Delete
  6. Anonymous15/8/16 16:25

    同樓上幾位大大。
    我也持續出現:


    GPS is not fixed yet.

    但手機可以偵測的到gps

    ReplyDelete
    Replies
    1. 手機可以偵測的到gps,這是第一步,
      然後要抓到fix。

      Delete
    2. Anonymous15/8/16 20:03

      請問大大,如果放在室外約一小時半還是抓不到的話呢...

      Delete
    3. 換地方。
      換板子。
      去LinkIt ONE論壇抗議。

      Delete
  7. 大大你好
    如果想要改成日期西元幾年幾月幾號
    請問還是可以用GPS嗎
    那字元的部份是要取多少呢??

    ReplyDelete
    Replies
    1. 日期,GPRMC與GPZDA裡面有,看看linkit api有沒有提供。

      > 字元的部份是要取多少呢??
      看不懂你的問題。

      Delete
  8. 請教一下
    您使用的GPS模組叫什麼?
    台灣的標準時間能顯示在七段上嗎?

    ReplyDelete
    Replies
    1. 就是LinkIt ONE的GPS模組。

      可抓到時間,再想辦法轉換時區,並顯示。

      Delete