I am working with a U-Blox GPS unit, that I need to configure via the serial port by sending specific sentences to it.
Every sentence I send has a checksum in the last two bytes of the sentence. Therefore I made a small sketch, where I paste a UBLOX command string into my sketch, and my sketch calculates the checksum. I then add the two calculated checksum bytes, to the command string and use that as the UBLOX sentence to send to my GPS.
Here is my sketch that I have tested and it works fine. The output it generates is CK_A = 91 and CK_B = 84
/*UBlox GPS message checksum calculator
V1.0 by Hans Meijdam
This sketch will calculate the UBLOX checksum. The checksum algorithm used is the 8-Bit Fletcher Algorithm, which is used in the TCP standard (RFC 1145).
leave out the first two sync-char of the UBLOX sentence and the last two bytes are the checksum bytes.
expected outcome of the below example should be: CK_A = 91 and CK_B = 84
*/
const static uint8_t myStr[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x84};
// ====sync=== ============================================== checksum calculated over these bytes =========================================================== =checksum=
void setup() {
Serial.begin(9600);
uint8_t CK_A = 0;
uint8_t CK_B = 0;
uint8_t i;
for (i = 0; i < sizeof(myStr) - 4; i++) { // "-4" because leave the first two and the last two bytes out of the checksum calculation.
CK_A = CK_A + myStr[i + 2]; // "+2" because we skip the first 2 sync bytes
CK_B = CK_B + CK_A;
}
Serial.print("CK_A = ");
Serial.print(CK_A, HEX);
Serial.print(" and CK_B = ");
Serial.println(CK_B, HEX);
}
void loop() {
}
So then I thought. "why waste dynamic ram if I can also store the array in PROGMEM?", so I changed this line
const static uint8_t myStr[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x84};
into this line
const static uint8_t myStr[] PROGMEM = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x84};
but now the output is: CK_A = 24 and CK_B = 91
I would like to understand what is causing the difference. I always assumed I can use static constants from PROGMEM and it will be like they were stored in RAM. But I fear my assumption is wrong.
note: I shuffled the position of PROGMEM around, as that seems to matter for the compiler, but in this case did not make a difference.