1

新しい GPS シールドを Teensy 3.1 (Arduino 互換) マイクロコントローラーでうまく動作させる方法がわからないため、数日間キーボードに頭をぶつけていました。

問題の GPS シールドはiteaduino ベースのもので、ここで見ることができます。

TinyGPS Arduino ライブラリを使用して、Teensy の UART ピンで NEO 6 gps モジュールからの受信データを解析し、緯度と経度を Arduino IDE のシリアル モニターに出力することに問題はありません。

NEO 6 に NMEA コマンドまたは UBX コマンドを発行しようとすると、問題が発生します。モジュールを実際に制御する唯一の方法は、同じ 6 つの NMEA メッセージを毎秒送信するだけではありません。(たとえば、UBX RXM-PMREQ コマンドを発行しないと、モジュールを省電力モードに設定できません)。

ukhas が提供する例に基づいてコードを作成することから始めましたが、それを機能させることができませんでした。そこで、基本的に次のことを行う簡単な小さなプログラムを作成しました。

  1. NEO 6 モジュールへのシリアル通信を 9600 ボーで確立
  2. UBX プロトコルに従う 11 バイトのデータ パケットを GPS モジュールに送信し、NMEA 緯度/経度メッセージの送信を停止するように指示します。
  3. GPS モジュールからの着信データ パケットを解析して、ACK (確認応答) メッセージを検索します。

確認メッセージは来ません!私は何を間違っていますか?!

これが私のコードです:

#include <HardwareSerial.h>
#include <string.h>
#include <TinyGPS.h>

void gpsdump(TinyGPS &gps);
void printFloat(double f, int digits = 2);

HardwareSerial2 GPS= HardwareSerial2();  //Initialize harware serial object for the GPS unit
TinyGPS gps;
byte gps_set_sucess = 0 ;

//Pin Definitions
int GPS_RxPin= 9;
int GPS_TxPin=10;

//I/O variables
int GPSbaud = 9600;
int Serialbaud=19200;

int byteCount;


//----------------------------------GPS unit functions------------------------------------------------

// Send a byte array of UBX protocol to the GPS
void sendUBX(uint8_t *MSG, uint32_t len, long timeout=3000) {

  uint32_t CK_A = 0, CK_B = 0;
  uint8_t sum1=0x00, sum2=0x00;
  uint8_t fullPacket[len+4];

  for(int i=0; i<len; i++) {
    fullPacket[i+2]=MSG[i];
  }

  Serial.println();
  fullPacket[0]=0xB5;
  fullPacket[1]= 0x62;

  //Calculate checksum
  for(int i=0; i<len; i++){
    CK_A = CK_A + MSG[i];
    CK_B = CK_B + CK_A;
    Serial.println("CK_A= " + String(CK_A));
    Serial.println("CK_B= " + String(CK_B));
  }

  sum1 = CK_A &0xff;//Mask the checksums to be one byte
  sum2= CK_B &0xff;

  fullPacket[len+2]=sum1; //Add the checksums to the end of the UBX packet
  fullPacket[len+3]=sum2;

  Serial.print("Checksum 1 premask= ");
  Serial.println(CK_A,HEX);
  Serial.print("Checksum 1 postmask= ");
  Serial.println(sum1, HEX);

  Serial.print("Checksum 2 premask= ");
  Serial.println(CK_B,HEX);
  Serial.print("Checksum 2 postmask= ");
  Serial.println(sum2, HEX);

  Serial.println("fullPacket is:");

  for(int i=0; i<(len+4); i++) { 
    Serial.print(fullPacket[i],HEX);//Print out a byt of the UBX data packet to the serial monitor
    Serial.print(", ");
    GPS.write(fullPacket[i]);//Send a byte of the UBX data packet to the GPS unit
  }
  GPS.clear(); 
  Serial.println();
}//end function


// Calculate expected UBX ACK packet and parse UBX response from GPS--------------------------
boolean getUBX_ACK(uint8_t *MSG, uint32_t len) {
  uint8_t b;
  uint8_t ackByteID = 0;
  uint8_t ackPacket[10];
  unsigned long startTime = millis();
  uint32_t CK_A=0, CK_B=0;
  boolean notAcknowledged=false;

 Serial.print(" * Reading ACK response: ");
  // Construct the expected ACK packet    
  ackPacket[0] = 0xB5;  // header
  ackPacket[1] = 0x62;  // header
  ackPacket[2] = 0x05;  // class
  ackPacket[3] = 0x01;  // id
  ackPacket[4] = 0x02;  // length
  ackPacket[5] = 0x00;
  ackPacket[6] = MSG[0];    // MGS class
  ackPacket[7] = MSG[1];    // MSG id
  ackPacket[8] = 0;     // CK_A
  ackPacket[9] = 0;     // CK_B

  // Calculate the checksums
  for (uint8_t i=2; i<8; i++) {
    CK_A = CK_A + ackPacket[i];
    CK_B= CK_B + CK_A;
  }

  ackPacket[8]= CK_A &0xff;//Mask the checksums to be one byte
  ackPacket[9]= CK_B &0xff;

  Serial.println("Searching for UBX ACK response:");
  Serial.print("Target data packet: ");

  for(int i =0; i<10; i++) {
    Serial.print(ackPacket[i], HEX);
    Serial.print(", ");
    }

  Serial.println();
  Serial.print("Candidate   packet: ");

  while (1) {

    // Test for success
    if (ackByteID > 9) {
      // All packets in order!
      Serial.println(" (Response received from GPS unit:)");
      if(notAcknowledged){
        Serial.println("ACK-NAK!");
      }
      else{
        Serial.println("ACK-ACK!");
        return true;
      }
    }

    // Timeout if no valid response in 5 seconds
    if (millis() - startTime > 5000) { 
      Serial.println("<<<Response timed out!>>>");
      return false;
    }

    // Make sure data is available to read
    if (GPS.available()) {
      b = GPS.read();

      // Check that bytes arrive in sequence as per expected ACK packet
      if (b == ackPacket[ackByteID]) { 
        ackByteID++;
        Serial.print(b, HEX);
        Serial.print(", ");
        // Check if message was not acknowledged
        if (ackByteID==3){
          b=GPS.read();
          if (b==0x00){
            notAcknowledged=true;
            ackByteID++;
          }
        }
      } 
      else if(ackByteID>0){
        ackByteID = 0;  // Reset and look again, invalid order
        Serial.print(b,HEX);
        Serial.println(" -->NOPE!");
        Serial.print("Candidate   packet: ");    
      }

    }
  }//end while
}//end function

//--------SETUP------------------

void setup()
{
  boolean gps_get_success=false;

  delay(5000);//Give yourself time to open up the serial monitor  

  pinMode(GPS_TxPin,OUTPUT); //Define the UART transmission pin for ommunication with the GPS unit
  pinMode(GPS_RxPin,INPUT); // Define the UART read pin for communication with the GPS unit

 Serial.begin(Serialbaud);  //Begin serial ommunication with Serial Monitor
 Serial.println("Serial monitor operational");
 GPS.begin(GPSbaud);  //Begin serial communication with GPS unit

 //Compile a UBX data packet to send to GPS - turn off GLL reporting
 uint8_t disableGLL[] = {0x06, 0x01, 0x03, 0x00, 0xF0, 0x01, 0x00};
 uint32_t len= sizeof(disableGLL)/sizeof(uint8_t); 

 Serial.println("Attempting to send UBX command to turn of GLL reporting");
 Serial.println("Original message is " + String(len) + " bytes:");

  for(int i=0; i<len; i++) {
    Serial.print(disableGLL[i]);
    Serial.print(", ");
  }
  Serial.println();

   //Clear the communication buffer
   while ( GPS.available())
    {
      char c = GPS.read();
    }

 sendUBX(disableGLL, len);
 getUBX_ACK(disableGLL, len);


}

//--------MAIN LOOP-------MAIN LOOP-------MAIN LOOP-------MAIN LOOP-------MAIN LOOP-------MAIN LOOP--
void loop()
{
  while ( GPS.available())
    {
      char c = GPS.read();
      if(c==0xb5){Serial.println();}
      Serial.print(c, HEX); // uncomment this line if you want to see the GPS data flowing
      Serial.print(", ");
    }

}//END LOOP-------------------

GPS モジュールがコマンドに応答しない理由がよくわかりません。それは横柄に見え始めています。シリアル モニタの出力は次のとおりです。

Serial monitor operational
Attempting to send UBX command to turn of GLL reporting
Original message is 7 bytes:
6, 1, 3, 0, 240, 1, 0, 

CK_A= 6
CK_B= 6
CK_A= 7
CK_B= 13
CK_A= 10
CK_B= 23
CK_A= 10
CK_B= 33
CK_A= 250
CK_B= 283
CK_A= 251
CK_B= 534
CK_A= 251
CK_B= 785
Checksum 1 premask= FB
Checksum 1 postmask= FB
Checksum 2 premask= 311
Checksum 2 postmask= 11
fullPacket is:
B5, 62, 6, 1, 3, 0, F0, 1, 0, FB, 11, 
 * Reading ACK response: Searching for UBX ACK response:
Target data packet: B5, 62, 5, 1, 2, 0, 6, 1, F, 38, 
Candidate   packet: B5, 38 -->NOPE!
Candidate   packet: B5, CC -->NOPE!
Candidate   packet: B5, 38 -->NOPE!
Candidate   packet: <<<Response timed out!>>>

そして、これはUARTを介して入ってくる生のバイトの例です(これらはarduinoのシリアルモニターに送信されました)

B5, 38, 35, FC, 10, 40, A1, 59, 3C, 10, 1D, 3C, 30, 11, BD, 19, 90, 18, 10, 48, BD, 51, 39, 1C, 3C, 10, 39, 5D, BC, 91, 91, 59, 3D, B9, B1, B1, 10, D5, 3C, B0, 59, 3D, 3C, 10, 91, 3D, B8, BC, 90, 19, 38, BC, 10, 48, BD, 11, 1D, 1C, 38, 50, 39, 11, 1D, 18, 3C, 11, B9, 1D, 3D, 1, 17, 11, 59, BC, 3C, 10, 5D, 18, B8, 50, 9D, 31, AC, 42, 1D, 5C, 71, 98, B1, 3C, B, 99, 59, 8A, 39, 1, CD, 19, 59, A, BC, 18, 31, 9D, 9D, BC, 31, A5, 86, 94, 32, B1, 0, 85, 25, B1, A5, 1C, 8A, 30, 1, 10, 19, 59, 99, 1D, 38, 31, 63, 84, B, B8, 19, BD, 
4

4 に答える 4

1

チェックサムの計算に問題があります。チェックサム変数は uint32_t として宣言されており、uint8_t として宣言する必要があります。または、次のように、追加するたびにマスクする必要があります。

  //Calculate checksum
  for(int i=0; i<len; i++){
    CK_A = CK_A + MSG[i];
    CK_A &= 0xFF;
    CK_B = CK_B + CK_A;
    CK_B &= 0xFF;
    Serial.println("CK_A= " + String(CK_A));
    Serial.println("CK_B= " + String(CK_B));
  }
于 2015-07-23T10:27:19.660 に答える
0

私はそのコードで同じ問題を抱えていました。私はHabduinoコードを使用しました.これは、MAX8 GPSモジュールと同じですが. Ublox NEO-6M のすべてのコマンドを確認する必要がありましたが、同じように見えました。しかし、あなたが持っていたのと同じ問題。

uCenterを開いて解決しました。メッセージ ビュー (F9) よりも、すべての NMEA および UBX (子) メッセージを無効にします。私の場合、デフォルトでUBX-POSLLHメッセージが有効になっていました。UBX-CFG-CFG を選択し、[送信] をクリックして、設定を UBX-CFG-CFG の下に保存します。

「HardwareSerial」ライブラリがわかりません。GPS を Arduino のハードウェア UART (ピン 0 と 1) に接続しました。つまり、監視するシリアルがないことを意味しますが、この非常に便利なトリックを使用しました: http://ava.upuaut.net/?p=757

NEO-6M からの UBX メッセージを無効にする方法を知っている人がいたら教えてください。ドキュメントは私にはそれについて明確ではありません。ありがとう!

于 2015-04-28T10:06:33.500 に答える
0

@ジャスティン、CSの計算に問題はありません。彼が提供したパケットは整形式なので、確認してください。

32 ビットの CS 変数を使用するのは無駄かもしれませんが、間違ったチェックサムを生成することはありません。どちらの場合も(送信と受信)、計算の最後にそれらをマスクします。

同じ ublox Neo-6M デバイスでこれを確認しました。私は、(現在) 最速かつ最小の NMEA+UBX パーサーであるNeoGPSの作成者です。

于 2015-09-20T19:23:02.827 に答える