Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Commit 495e6c7

Browse files
committed
Improving the low-level sendCommand function.
Removes unneeded coms when we're just sending a query command (packet length = 0). Releases bus if packet length is 0.
1 parent 8d6d0eb commit 495e6c7

File tree

2 files changed

+149
-91
lines changed

2 files changed

+149
-91
lines changed

Diff for: src/SparkFun_Ublox_Arduino_Library.cpp

+144-87
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ void SFE_UBLOX_GPS::begin(TwoWire &wirePort)
4646
//ie, there are some platforms that don't handle multiple starts to the wire hardware. Also, every time you start the wire
4747
//hardware the clock speed reverts back to 100kHz regardless of previous Wire.setClocks().
4848
//_i2cPort->begin();
49-
50-
setI2CReadAddress(0x42); //By default, use 0x42
5149
}
5250

5351
//Sets the internal global variable that is the I2C address we read from
@@ -142,7 +140,7 @@ void SFE_UBLOX_GPS::process(uint8_t incoming)
142140
{
143141
if (currentSentence == NONE || currentSentence == NMEA)
144142
{
145-
if (incoming == 0xB5) //UBX binary frames start with 0xB5
143+
if (incoming == 0xB5) //UBX binary frames start with 0xB5, aka μ
146144
{
147145
//This is the start of a binary sentence. Reset flags.
148146
//We still don't know the response class
@@ -168,9 +166,9 @@ void SFE_UBLOX_GPS::process(uint8_t incoming)
168166
if (currentSentence == UBX)
169167
{
170168
//Decide what type of response this is
171-
if (ubxFrameCounter == 0 && incoming != 0xB5)
169+
if (ubxFrameCounter == 0 && incoming != 0xB5) //ISO 'μ'
172170
currentSentence = NONE; //Something went wrong. Reset.
173-
else if (ubxFrameCounter == 1 && incoming != 0x62)
171+
else if (ubxFrameCounter == 1 && incoming != 0x62) //ASCII 'b'
174172
currentSentence = NONE; //Something went wrong. Reset.
175173
else if (ubxFrameCounter == 2) //Class
176174
{
@@ -199,7 +197,12 @@ void SFE_UBLOX_GPS::process(uint8_t incoming)
199197
else
200198
{
201199
#ifdef DEBUG
202-
debug.println(F("No frame class set"));
200+
//Print this character
201+
debug.print(F("No frame class set: "));
202+
debug.write(incoming);
203+
debug.print(" 0x");
204+
debug.print(incoming, HEX);
205+
debug.println();
203206
#endif
204207
}
205208
}
@@ -287,56 +290,63 @@ void SFE_UBLOX_GPS::processRTCM(uint8_t incoming)
287290

288291
//Given a character, file it away into the uxb packet structure
289292
//Set valid = true once sentence is completely received and passes CRC
293+
//The payload portion of the packet can be 100s of bytes but the max array
294+
//size is roughly 64 bytes. startingSpot can be set so we only record
295+
//interim bytes.
290296
void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX)
291297
{
292-
if (incomingUBX->counter == 0)
293-
{
294-
incomingUBX->cls = incoming;
295-
}
296-
else if (incomingUBX->counter == 1)
297-
{
298-
incomingUBX->id = incoming;
299-
}
300-
else if (incomingUBX->counter == 2) //Len LSB
301-
{
302-
incomingUBX->len = incoming;
303-
}
304-
else if (incomingUBX->counter == 3) //Len MSB
305-
{
306-
incomingUBX->len |= incoming << 8;
307-
}
308-
else if (incomingUBX->counter == incomingUBX->len + 4) //ChecksumA
309-
{
310-
incomingUBX->checksumA = incoming;
311-
}
312-
else if (incomingUBX->counter == incomingUBX->len + 5) //ChecksumB
313-
{
314-
//Validate this sentence
298+
if (incomingUBX->counter == 0)
299+
{
300+
incomingUBX->cls = incoming;
301+
}
302+
else if (incomingUBX->counter == 1)
303+
{
304+
incomingUBX->id = incoming;
305+
}
306+
else if (incomingUBX->counter == 2) //Len LSB
307+
{
308+
incomingUBX->len = incoming;
309+
}
310+
else if (incomingUBX->counter == 3) //Len MSB
311+
{
312+
incomingUBX->len |= incoming << 8;
313+
}
314+
else if (incomingUBX->counter == incomingUBX->len + 4) //ChecksumA
315+
{
316+
incomingUBX->checksumA = incoming;
317+
}
318+
else if (incomingUBX->counter == incomingUBX->len + 5) //ChecksumB
319+
{
320+
//Validate this sentence
315321

316-
uint8_t tempA = incomingUBX->checksumA;
317-
uint8_t tempB = incoming;
322+
uint8_t tempA = incomingUBX->checksumA;
323+
uint8_t tempB = incoming;
318324

319-
calcChecksum(incomingUBX); //Calc checksum across this message. Results stored in message.
325+
calcChecksum(incomingUBX); //Calc checksum across this message. Results stored in message.
320326

321-
currentSentence = NONE; //We're done! Reset the sentence to being looking for a new start char
327+
currentSentence = NONE; //We're done! Reset the sentence to being looking for a new start char
322328

323-
if (incomingUBX->checksumA == tempA && incomingUBX->checksumB == tempB)
324-
{
329+
if (incomingUBX->checksumA == tempA && incomingUBX->checksumB == tempB)
330+
{
325331
#ifdef DEBUG
326-
debug.print("Frame cleared: ");
327-
//printFrame(incomingUBX);
332+
debug.print("Frame cleared: ");
333+
//printFrame(incomingUBX);
328334
#endif
329335

330-
incomingUBX->valid = true;
331-
processUBXpacket(incomingUBX); //We've got a valid packet, now do something with it
332-
}
333-
}
334-
else //Load this byte into the payload array
335-
{
336-
//Check to see if we have room for this byte
337-
if( (incomingUBX->counter - 4) < MAX_PAYLOAD_SIZE)
338-
incomingUBX->payload[incomingUBX->counter - 4] = incoming; //Store this byte into payload array
339-
}
336+
incomingUBX->valid = true;
337+
processUBXpacket(incomingUBX); //We've got a valid packet, now do something with it
338+
}
339+
}
340+
else //Load this byte into the payload array
341+
{
342+
//Begin recording if counter goes past startingSpot
343+
if(incomingUBX->counter > incomingUBX->startingSpot)
344+
{
345+
//Check to see if we have room for this byte
346+
if( (incomingUBX->counter - 4) < MAX_PAYLOAD_SIZE)
347+
incomingUBX->payload[incomingUBX->counter - 4 + incomingUBX->startingSpot] = incoming; //Store this byte into payload array
348+
}
349+
}
340350

341351
incomingUBX->counter++;
342352
}
@@ -368,6 +378,8 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg)
368378
}
369379

370380
//Given a packet and payload, send everything including CRC bytes
381+
//Poll for a response, returning true if command was ack'd, false if we time out waiting for response
382+
//Setting timeout to 0 will skip checking for response - handy if you need to scan a raw response (like checking the PROTVER)
371383
boolean SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t maxWait)
372384
{
373385
commandAck = false; //We're about to send a command. Begin waiting for ack.
@@ -388,42 +400,51 @@ boolean SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t maxWait)
388400
_i2cPort->write(outgoingUBX.id);
389401
_i2cPort->write(outgoingUBX.len & 0xFF); //LSB
390402
_i2cPort->write(outgoingUBX.len >> 8); //MSB
391-
if (_i2cPort->endTransmission(false) != 0) //Don't release bus
392-
return (false); //Sensor did not ACK
393-
394-
//Write payload. Limit the sends into 32 byte chunks
395-
//This code based on ublox: https://forum.u-blox.com/index.php/20528/how-to-use-i2c-to-get-the-nmea-frames
396-
uint16_t bytesToSend = outgoingUBX.len;
403+
404+
//Normally we would endTransmission() here but instead, we check if there are more bytes to transmit.
397405

398-
//"The number of data bytes must be at least 2 to properly distinguish
399-
//from the write access to set the address counter in random read accesses."
400-
uint16_t startSpot = 0;
401-
while (bytesToSend > 1)
406+
//If we are sending just a command, there are no bytes to send so skip sending anything.
407+
if(outgoingUBX.len > 0)
402408
{
403-
uint8_t len = bytesToSend;
404-
if (len > I2C_BUFFER_LENGTH) len = I2C_BUFFER_LENGTH;
405-
406-
_i2cPort->beginTransmission((uint8_t)_gpsI2Caddress);
407-
//_i2cPort->write(outgoingUBX.payload, len); //Write a portion of the payload to the bus
408-
409-
for (uint16_t x = 0 ; x < len ; x++)
410-
_i2cPort->write(outgoingUBX.payload[startSpot + x]); //Write a portion of the payload to the bus
411-
412-
if (_i2cPort->endTransmission(false) != 0) //Don't release bus
413-
return (false); //Sensor did not ACK
414-
415-
//*outgoingUBX.payload += len; //Move the pointer forward
416-
startSpot += len; //Move the pointer forward
417-
bytesToSend -= len;
409+
if (_i2cPort->endTransmission(false) != 0) //Do not release bus
410+
return (false); //Sensor did not ACK
411+
412+
//Write payload. Limit the sends into 32 byte chunks
413+
//This code based on ublox: https://forum.u-blox.com/index.php/20528/how-to-use-i2c-to-get-the-nmea-frames
414+
uint16_t bytesToSend = outgoingUBX.len;
415+
416+
//"The number of data bytes must be at least 2 to properly distinguish
417+
//from the write access to set the address counter in random read accesses."
418+
uint16_t startSpot = 0;
419+
while (bytesToSend > 1)
420+
{
421+
uint8_t len = bytesToSend;
422+
if (len > I2C_BUFFER_LENGTH) len = I2C_BUFFER_LENGTH;
423+
424+
_i2cPort->beginTransmission((uint8_t)_gpsI2Caddress);
425+
//_i2cPort->write(outgoingUBX.payload, len); //Write a portion of the payload to the bus
426+
427+
for (uint16_t x = 0 ; x < len ; x++)
428+
_i2cPort->write(outgoingUBX.payload[startSpot + x]); //Write a portion of the payload to the bus
429+
430+
if (_i2cPort->endTransmission(false) != 0) //Don't release bus
431+
return (false); //Sensor did not ACK
432+
433+
//*outgoingUBX.payload += len; //Move the pointer forward
434+
startSpot += len; //Move the pointer forward
435+
bytesToSend -= len;
436+
}
437+
438+
//Write checksum
439+
_i2cPort->beginTransmission((uint8_t)_gpsI2Caddress);
440+
if (bytesToSend == 1) _i2cPort->write(outgoingUBX.payload, 1);
441+
_i2cPort->write(outgoingUBX.checksumA);
442+
_i2cPort->write(outgoingUBX.checksumB);
418443
}
419-
420-
//Write checksum
421-
_i2cPort->beginTransmission((uint8_t)_gpsI2Caddress);
422-
if (bytesToSend == 1) _i2cPort->write(outgoingUBX.payload, 1);
423-
_i2cPort->write(outgoingUBX.checksumA);
424-
_i2cPort->write(outgoingUBX.checksumB);
444+
445+
//All done transmitting bytes. Release bus.
425446
if (_i2cPort->endTransmission() != 0)
426-
return (false); //Sensor did not ACK
447+
return (false); //Sensor did not ACK
427448

428449
if (maxWait > 0)
429450
{
@@ -499,6 +520,7 @@ boolean SFE_UBLOX_GPS::getSurveyMode(uint16_t maxWait)
499520
packetCfg.cls = UBX_CLASS_CFG;
500521
packetCfg.id = UBX_CFG_TMODE3;
501522
packetCfg.len = 0;
523+
packetCfg.startingSpot = 0;
502524

503525
return ( sendCommand(packetCfg, maxWait) );
504526
}
@@ -513,7 +535,12 @@ boolean SFE_UBLOX_GPS::setSurveyMode(uint8_t mode, uint16_t observationTime, flo
513535
packetCfg.cls = UBX_CLASS_CFG;
514536
packetCfg.id = UBX_CFG_TMODE3;
515537
packetCfg.len = 40;
538+
packetCfg.startingSpot = 0;
516539

540+
//Clear packet payload
541+
for(uint8_t x = 0 ; x < packetCfg.len ; x++)
542+
packetCfg.payload[x] = 0;
543+
517544
//payloadCfg should be loaded with poll response. Now modify only the bits we care about
518545
payloadCfg[2] = mode; //Set mode. Survey-In and Disabled are most common.
519546

@@ -550,6 +577,7 @@ boolean SFE_UBLOX_GPS::getSurveyStatus(uint16_t maxWait)
550577
packetCfg.cls = UBX_CLASS_NAV;
551578
packetCfg.id = UBX_NAV_SVIN;
552579
packetCfg.len = 0;
580+
packetCfg.startingSpot = 0;
553581

554582
//Reset variables
555583
svin.active = false;
@@ -592,6 +620,7 @@ boolean SFE_UBLOX_GPS::enableRTCMmessage(uint8_t messageNumber, uint8_t portID,
592620
packetCfg.cls = UBX_CLASS_CFG;
593621
packetCfg.id = UBX_CFG_MSG;
594622
packetCfg.len = 8;
623+
packetCfg.startingSpot = 0;
595624

596625
//Clear packet payload
597626
for(uint8_t x = 0 ; x < packetCfg.len ; x++)
@@ -620,6 +649,11 @@ boolean SFE_UBLOX_GPS::setRTCMport(uint8_t portID, boolean enableRTCM3, uint16_t
620649
packetCfg.cls = UBX_CLASS_CFG;
621650
packetCfg.id = UBX_CFG_PRT;
622651
packetCfg.len = 20;
652+
packetCfg.startingSpot = 0;
653+
654+
//Clear packet payload
655+
for(uint8_t x = 0 ; x < packetCfg.len ; x++)
656+
packetCfg.payload[x] = 0;
623657

624658
//msg_payload is now loaded with current bytes. Change only the ones we need to
625659
payloadCfg[13] |= (1 << 5); //InProtocolMask LSB - Set inRtcm3
@@ -634,6 +668,8 @@ boolean SFE_UBLOX_GPS::getPortSettings(uint8_t portID, uint16_t maxWait)
634668
packetCfg.cls = UBX_CLASS_CFG;
635669
packetCfg.id = UBX_CFG_PRT;
636670
packetCfg.len = 1;
671+
packetCfg.startingSpot = 0;
672+
637673
payloadCfg[0] = portID;
638674

639675
return ( sendCommand(packetCfg, maxWait) );
@@ -646,6 +682,7 @@ uint32_t SFE_UBLOX_GPS::getPositionAccuracy(uint16_t maxWait)
646682
packetCfg.cls = UBX_CLASS_NAV;
647683
packetCfg.id = UBX_NAV_HPPOSECEF;
648684
packetCfg.len = 0;
685+
packetCfg.startingSpot = 0;
649686

650687
if(sendCommand(packetCfg, maxWait) == false)
651688
return(0); //If command send fails then bail
@@ -670,8 +707,10 @@ int32_t SFE_UBLOX_GPS::getLatitude(uint16_t maxWait)
670707
packetCfg.cls = UBX_CLASS_NAV;
671708
packetCfg.id = UBX_NAV_POSLLH;
672709
packetCfg.len = 0;
710+
packetCfg.startingSpot = 0;
673711

674-
if(sendCommand(packetCfg, maxWait) == false)
712+
// if(sendCommand(packetCfg, maxWait) == false)
713+
if(sendCommand(packetCfg, 1500) == false)
675714
return(0); //If command send fails then bail
676715

677716
//We got a response, now parse the byte fields
@@ -692,6 +731,7 @@ int32_t SFE_UBLOX_GPS::getLongitude(uint16_t maxWait)
692731
packetCfg.cls = UBX_CLASS_NAV;
693732
packetCfg.id = UBX_NAV_POSLLH;
694733
packetCfg.len = 0;
734+
packetCfg.startingSpot = 0;
695735

696736
if(sendCommand(packetCfg, maxWait) == false)
697737
return(0); //If command send fails then bail
@@ -715,6 +755,7 @@ int32_t SFE_UBLOX_GPS::getAltitudeEllipsoid(uint16_t maxWait)
715755
packetCfg.cls = UBX_CLASS_NAV;
716756
packetCfg.id = UBX_NAV_POSLLH;
717757
packetCfg.len = 0;
758+
packetCfg.startingSpot = 0;
718759

719760
if(sendCommand(packetCfg, maxWait) == false)
720761
return(0); //If command send fails then bail
@@ -738,6 +779,7 @@ int32_t SFE_UBLOX_GPS::getAltitude(uint16_t maxWait)
738779
packetCfg.cls = UBX_CLASS_NAV;
739780
packetCfg.id = UBX_NAV_POSLLH;
740781
packetCfg.len = 0;
782+
packetCfg.startingSpot = 0;
741783

742784
if(sendCommand(packetCfg, maxWait) == false)
743785
return(0); //If command send fails then bail
@@ -753,19 +795,34 @@ int32_t SFE_UBLOX_GPS::getAltitude(uint16_t maxWait)
753795
}
754796

755797
//Get the current protocol version of the Ublox module we're communicating with
756-
//This is helpful when deiciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH)
798+
//This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH)
757799
uint8_t SFE_UBLOX_GPS::getProtocolVersionHigh(uint16_t maxWait)
758800
{
759801
//Send packet with only CLS and ID, length of zero. This will cause the module to respond with the contents of that CLS/ID.
760802
packetCfg.cls = UBX_CLASS_MON;
761803
packetCfg.id = UBX_MON_VER;
762804
packetCfg.len = 0;
763805

764-
if(sendCommand(packetCfg, maxWait) == false)
765-
return(0); //If command send fails then bail
766-
767-
//We got a response, now find the extension that contains 'PROTVER'
768-
//The response for this register can be quite large, many hundreds of bytes so we have to use a new, much larger array
806+
//We will send the command repeatedly, increasing the startingSpot as we go
807+
//Then we look at each extension field of 30 bytes
808+
for(uint8_t extensionNumber = 0 ; extensionNumber < 1 ; extensionNumber++)
809+
{
810+
packetCfg.startingSpot = 40 + (30*extensionNumber);
811+
812+
if(sendCommand(packetCfg, maxWait) == false)
813+
return(0); //If command send fails then bail
814+
815+
while(1);
816+
817+
//Now we need to start looking for "PROTVER" in the incoming byte stream
818+
Serial.print("Extension: ");
819+
for(int location ; location < 64 ; location++)
820+
{
821+
Serial.write(packetCfg.payload[location]);
822+
if(packetCfg.payload[location] == '\0') break;
823+
}
824+
Serial.println();
825+
}
769826

770827
return(0);
771-
}
828+
}

0 commit comments

Comments
 (0)