Итак, я бился головой о клавиатуру в течение нескольких дней, потому что не могу понять, как заставить мой новый экран GPS хорошо работать с моим микроконтроллером Teensy 3.1 (совместимым с Arduino).
Рассматриваемый экран GPS создан на основе iteaduino, и его можно увидеть здесь.
У меня нет проблем с использованием библиотеки TinyGPS Arduino для анализа входящих данных из модуля NEO 6 gps на выводах UART Teensy и вывода широты и долготы на мой последовательный монитор в Arduino IDE.
Проблема возникает, когда я пытаюсь передать NEO 6 команду NMEA или команду UBX. Это единственный способ фактически управлять модулем, вместо того, чтобы позволить ему отправлять одни и те же 6 сообщений NMEA каждую секунду. (например, вы не можете установить модуль в режим энергосбережения, не выполнив команду UBX RXM-PMREQ).
Я начал с того, что основал свой код на примере , предоставленном ukhas, но не смог заставить его работать . Итак, я сделал простую небольшую программу, которая в основном выполняет следующие функции:
- Устанавливает последовательную связь с модулем NEO 6 на скорости 9600 бод.
- Отправляет модулю GPS 11-байтовый пакет данных, который следует протоколу UBX, говоря ему, чтобы он прекратил отправку сообщений NMEA lat / lon
- Анализирует входящие пакеты данных от модуля 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,