8 years, 4 months ago.

Disable message in u-blox cam m8 using C code

Dear All,

I am currently writing a C code and using Renesas uC to disable messages from the ublox cam m8 through UART0. I can successfully disable the message one at a time which means I can only disable one message after each compile and run. Hence, this sounds like it is a buffer issue to me.

Does anyone has the same kind of issue before? If so, could you tell me the method to solve it? Below is my code:

uint8_t clrDTM[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x0A ,0x00 ,0x04 ,0x23}; uint8_t clrGBS[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x09 ,0x00 ,0x03 ,0x21}; uint8_t clrGGA[12] = {11, 0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x00 ,0x00 ,0xFA ,0x0F}; uint8_t clrGLL[12] = {11, 0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x01 ,0x00 ,0xFB ,0x11}; uint8_t clrGLL[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x08 ,0x00 ,0xF0 ,0x01 ,0x00, 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x2A}; uint8_t clrGNS[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x0D ,0x00 ,0x07 ,0x29}; uint8_t clrGRS[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x06 ,0x00 ,0x00 ,0x1B}; uint8_t clrGSA[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x02 ,0x00 ,0xFC ,0x13}; uint8_t clrGST[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x07 ,0x00 ,0x01 ,0x1D}; uint8_t clrGSV[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x03 ,0x00 ,0xFD ,0x15}; uint8_t clrRMC[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x04 ,0x00 ,0xFE ,0x17}; uint8_t clrTHS[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x0E ,0x00 ,0x08 ,0x2B}; uint8_t clrVLW[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x0F ,0x00 ,0x09 ,0x2D}; uint8_t clrVTG[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x05 ,0x00 ,0xFF ,0x19}; uint8_t clrZDA[] = {0xB5 ,0x62 ,0x06 ,0x01 ,0x03 ,0x00 ,0xF0 ,0x08 ,0x00 ,0x02 ,0x1F};

R_UART0_Send(clrDTM, sizeof(clrDTM)); R_UART0_Send(clrGBS, sizeof(clrGBS)); R_UART0_Send(&clrGGA, sizeof(clrGGA)); R_UART0_Send(clrGLL, sizeof(clrGLL)); R_UART0_Send(clrGNS, sizeof(clrGNS)); R_UART0_Send(clrGRS, sizeof(clrGRS)); R_UART0_Send(clrGSA, sizeof(clrGSA)); R_UART0_Send(clrGST, sizeof(clrGST)); R_UART0_Send(clrGSV, sizeof(clrGSV)); R_UART0_Send(clrTHS, sizeof(clrTHS)); R_UART0_Send(clrVLW, sizeof(clrVLW)); R_UART0_Send(clrVTG, sizeof(clrVTG)); R_UART0_Send(clrZDA, sizeof(clrZDA));

}

The correct solution would be to wait for the acknowledge back from the ublox between each message. The simple solution is to add a worst case processing time pause between each message, 5-10 ms should be enough.

Also rather than hard coding the messages you could generate them on the fly:

void addChecksumAndSend (uint8_t* buffer, unsigned int size)
{
    uint8_t CKA = 0;
    uint8_t CKB = 0;
    for (int i = 2; i < size; i++) {
        CKA = CKA + buffer[i];
        CKB = CKB + CKA;
    }
    buffer[size] = CKA;
    buffer[size+1] = CKB;

    R_UART0_Send(buffer, size+2);
}

void setNMEAMessage(uint8_t messageID, bool enable)
{
    const int packetSize = 8; // number of data bytes
    uint8_t buffer[packetSize  + 8]; // data + 6 bytes header + 2 byte checksum
    uint8_t *payload = buffer + 6; // start of data

    buffer[0] = 0xB5; // Sync
    buffer[1] = 0x62;

    buffer[2] = 0x06; // command class - config
    buffer[3] = 0x01; // command ID - set message rates

    buffer[4] = packetSize; // payload length
    buffer[5] = 0; //

    *(uint8_t *) payload = 0xf0; // Message type NMEA
    *(uint8_t *)(payload + 1) = messageID; 
    *(uint8_t *)(payload + 2) = 0; // rate for other ports
    *(uint8_t *)(payload + 3) = (enable) ? 1 : 0; // serial port rate
    *(uint8_t *)(payload + 4) = 0; // rate for other ports
    *(uint8_t *)(payload + 5) = 0; // rate for other ports
    *(uint8_t *)(payload + 6) = 0; // rate for other ports
    *(uint8_t *)(payload + 7) = 0; // rate for other ports
     addChecksumAndSend(buffer, packetSize+6);
    }

If all you are doing is switching them off then this isn't worth the effort but if you want to be able to switch them (or other messages ) back on again at some point then it makes life a lot easier. You can easily adapt the same basic framework for any other config messages you may want to send.

posted by Andy A 29 Nov 2017

Thanks Andy. Just another question because I am quite new to the ublox and Renesas, how do I add a time pulse between each message since there is no built in delay command in C in Renesas. I have tried to put a for loop between each buffer. However, it would not work.

posted by Cheung Huang 29 Nov 2017

Hi Andy. May I also ask what does the below code do and how does it link to the buffer?

  • (uint8_t *) payload = 0xf0; Message type NMEA
  • (uint8_t *)(payload + 1) = messageID;
  • (uint8_t *)(payload + 2) = 0; rate for other ports
  • (uint8_t *)(payload + 3) = (enable) ? 1 : 0; serial port rate
  • (uint8_t *)(payload + 4) = 0; rate for other ports
  • (uint8_t *)(payload + 5) = 0; rate for other ports
  • (uint8_t *)(payload + 6) = 0; rate for other ports
  • (uint8_t *)(payload + 7) = 0; rate for other ports
posted by Cheung Huang 30 Nov 2017

Assuming you are using the mbed libraries then the command is wait(0.01); to wait 10ms. If you're not using mbed then you're asking questions in the wrong place.

As a general rule if you want to use a loop to add a delay make sure it's modifying a volatile variable so the compiler doesn't optimize it out. Something like:

const int loopsPerUs = 50; // as a first very crude approximation CPU speed in MHz/2;
volatile int x = 0;
while (x < 10*1000*loopsPerUs)
  x++;

Buffer is defined as an array that it large enough to hold the full message (header, data and checksum). payload is then defined as a point to the 6th byte in that buffer which is the first byte of the data part of the message (the Payload Contents part of the ublox documentation). I did it this way so that the numbers match up with the Byte Offset column in the Ublox documentation.

e.g. to set a variable that the manual says has a Byte Offest of 6 and a Number Format of I4 the command would be

*(int32_t)(payload + 6) = value;

The aim is to make the names and numbers in the code as close as possible to those in the documentation, it may make things a tiny bit more confusing when you first write the code but in the long term it makes for something that's a lot more maintainable. e.g. You don't need to remember to add offsets for the header size everywhere, payload points to the thing the document calls payload.

Also when posting code use

<<code>>
your code
<</code>>


It stops the website from messing up the formatting.

posted by Andy A 30 Nov 2017

Thanks Andy

posted by Cheung Huang 30 Nov 2017
Be the first to answer this question.