Announcement

Collapse
No announcement yet.

Why do I receive a NACK with every single WriteString?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Why do I receive a NACK with every single WriteString?

    Hey Everybody, (I cannot figure out how to place my code in a separate code window...please tell me how to do this)

    I am using a uLCD-70DT. I have written much of my own code and the only command I am having trouble with is the Write String command. It works great as the GPS coordinates that I am updating on the uLCD-70DT update just fine.

    On my logic analyzer, it appears that ACK/NACK's are being transmitted from the uLCD-70DT back to the Arduino MEGA 2560 microcontroller IN THE MIDDLE of the WriteString command (updateCurrentGPSLatCoords and updateCurrentGPSLonCoords). These commands get executed one after the other.
    See the attached PNG file showing a screen capture from the logic analyzer (IKA Scanalogic2).

    I am transmitting the following: "+26.16178"

    If you look carefully at the image, you can see that I am writing the following bytes to the uLCD-70DT:

    0x02 0x00 0x0A 0x2B 0x32 0x36 0x2E 0x31 0x36 0x31 0x37 0x38 0x00 030

    NACK' appear just after the 0x36 and another just after the 0x38. WHY IS THIS HAPPENING?

    I have tested my writestring function and it works fine with the correct XOR checksum.


    void manualNavigate(void)
    {
    eStop(); // stop before doing anything else
    thrusterMasterPower(1); // turn on thruster master power
    while((rx_byte[2] != 0x0E) || (rx_byte[2] != 0x0F)) // while BACK or ESTOP buttons are not pressed
    {
    getGPS();
    if (timer > millis()) timer = millis();
    if (millis() - timer > 250)
    {
    timer = millis(); // reset the timer
    if(GPS.fix)
    {
    updateCurrentGPSLatCoords(0x02, 0x00); //update current GPS latitude in manual navigate window
    updateCurrentGPSLonCoords(0x02, 0x07); //update current GPS longitude in manual navigate window
    }
    }
    getInput();
    }
    return;
    }
    Attached Files
    TIA,

    Neal

  • #2
    Do I need to break up my WriteString command into 6 byte increments? Send 6 bytes, send another 6 bytes, etc.???
    TIA,

    Neal

    Comment


    • John Kevin
      John Kevin commented
      Editing a comment
      Hi Neal,

      No, you don't have to. You can send the whole string message. Just specify the correct length and checksum.

      Best Regards,
      Kevin

  • #3
    This is my code for WriteString. If the heading is NORTH, then I copy a "+" sign to the latTemp variable in my code. I then do a decimal to string conversion, calculate the checksum, and then do the write string. I use the uLCD.flush() command to ensure that all bytes have been sent (i.e. transmit buffer is empty) prior to continuing.

    Code:
    void updateCurrentGPSLatCoords(byte CMD, byte ID)
    {
        byte checksum;
        int ln;
    
        if(GPS.lat == 'N')strcpy(gpsCURRENT.latTemp, "+");     //copy +/- symbol to Temp variable
        //else(strcpy(gpsCURRENT.latTemp, "-"));
    
        if(gpsCURRENT.latDegrees < 10)ln=7;                     //eliminates space between +/- and number when deg<10
        else(ln=8);
    
        dtostrf(gpsCURRENT.latDegrees, ln, 5, gpsCurrLatDeg);  //convert lat degrees to a string w/5 decimal places
    
        strcat(gpsCURRENT.latTemp,gpsCurrLatDeg);              //concatenate the numeric portion of the string to the +/- symbol
        strcpy(gpsCurrLatDeg, gpsCURRENT.latTemp);             //copy value back to gpsCurrLatDeg
    
        checksum = CMD;                              
        checksum ^= ID;                                
        if(strlen(gpsCurrLatDeg) == 9)                         //adjust stringlength bytes for checksum based upon stringlength
        {
            checksum ^= 0x0A;                                  //for latitude betw >=10 and <=180 degrees
        }
        else
        {
            checksum ^= 0x09;                                  //for latitude betw >0 and <10 degrees
        }  
        for(int i=0; i<(strlen(gpsCurrLatDeg)+1); i++)         //perform checksum byte by byte
        {
           if(gpsCurrLatDeg[i]>0 && gpsCurrLatDeg[i]<10)
           {
              checksum ^= (gpsCurrLatDeg[i] + '0');            //if byte is numeric, then add 0x30
           }
           else
           {
              checksum ^= gpsCurrLatDeg[i];                   //if byte is +, -, or ., then don't add 0x30
           }
        }
    
        uLCD.write(CMD);
        uLCD.write(ID);
        if(strlen(gpsCurrLatDeg) == 9)
        {
            uLCD.write(0x0A);                                  //adjust stringlength bytes for checksum based upon stringlength
        }
        else
        {
            uLCD.write(0x09);
        }  
        for(int i=0; i<(strlen(gpsCurrLatDeg)+1); i++)         //perform checksum byte by byte
        {
           if(gpsCurrLatDeg[i]>0 && gpsCurrLatDeg[i]<10)
           {
              uLCD.write(gpsCurrLatDeg[i] + '0');              //if byte is numeric, then add 0x30
           }
           else
           {
              uLCD.write(gpsCurrLatDeg[i]);                   //if byte is +, -, or ., then don't add 0x30
           }
        }
        uLCD.write(checksum);
        Serial1.flush();                                      //wait for transmit buffer to be empty
    }
    TIA,

    Neal

    Comment


    • #4
      Hi Neal,

      On my logic analyzer, it appears that ACK/NACK's are being transmitted from the uLCD-70DT back to the Arduino MEGA 2560 microcontroller IN THE MIDDLE of the WriteString command (updateCurrentGPSLatCoords and updateCurrentGPSLonCoords). These commands get executed one after the other.
      Code:
      if(GPS.fix)
      {
      updateCurrentGPSLatCoords(0x02, 0x00); //update current GPS latitude in manual navigate window
      updateCurrentGPSLonCoords(0x02, 0x07); //update current GPS longitude in manual navigate window
      }
      Looking at the updateCurrentGPSLatCoords(0x02, 0x00);, it appears that you don't have a routine to wait for the ACK before sending again the next 'Write String'. In the attached image, it seems that the NACK's come from the message after executing the 'Write String command. Before sending again another 'Write String' command, you must first wait for the ACK.

      Best Regards,
      Kevin

      Comment


      • #5
        Hi Neal,

        I have attached an example for your reference. I do hope that this can be helpful in your application.

        Best Regards,
        Kevin
        Attached Files

        Comment


        • #6
          Dear John,

          I have implemented this in my code with a few variable name changes, etc... This does not work.

          I cannot figure out why the CheckAck() function checks to see if(rx_byte[numBytes-1] == ACK) else if else if(rx_byte[numBytes-1] == NACK) else INVALID.

          The CheckAck() function has to work with a button press as well like writing 0x07 0x06 0x00 0x00 0x00 0x01. At the end of the serial read loop, you add one to numOfBytes, so this should be one more than the actual number of bytes. So in this last example with a button press, numOfBytes = 7, so when you print res[numOfBytes - 1], the last byte 0x01 should get serial printed to the serial monitor as "Response: 1".

          I think that your code with the 1ms delay is trying to receive a final ACK or NACK byte??? If that is true, then the last byte would be 0x06 or 0x15. Not 0x01.

          Is this correct?

          Do I need to flush the transmit buffer or receive buffer?

          TIA,
          --Neal
          TIA,

          Neal

          Comment


          • #7
            Dear Kevin,

            Thank you for all of your help.

            See attached image.

            I just wanted to update you on my progress, or lack thereof. I have run your code exactly as you provided it with 2 exceptions. I modified the baud rates to 115200 for the Serial monitor and 57600 for the uLCD. All I receive is an endless output of NACK's.

            So I re-ask the question per my prior response: Is the "last" byte received supposed to be the ACK/NACK response?

            I have been trying to solve this ACK/NACK issue for nearly 2 weeks with no solution in sight. NOTHING works!!! At first I thought that it was some "interference" between Serial1 and Serial2 on the Arduino MEGA 2560. And then I thought that it was a timing issue....and then something else. I have fixed each suspected cause of these issues. But everytime that I think that I have found the root cause, another issue appears.

            I think that I am going to replace the WriteStrings with Digits. The command seems to be much quicker...similar to my button presses and slider movements that all work.

            TIA,
            --Neal
            Attached Files
            TIA,

            Neal

            Comment


            • #8
              Hi Neal,

              Thank you for your reply.
              The CheckAck() function has to work with a button press as well like writing 0x07 0x06 0x00 0x00 0x00 0x01. At the end of the serial read loop, you add one to numOfBytes, so this should be one more than the actual number of bytes. So in this last example with a button press, numOfBytes = 7, so when you print res[numOfBytes - 1], the last byte 0x01 should get serial printed to the serial monitor as "Response: 1".
              The example that I have attached is exclusive only on the one-byte reply - 'ACK', which is what the host would be expecting to receive after using the 'Write Str' command. It does not verify the 6-byte report message which comes from the display. You may want to implement a separate condition for this.

              I just wanted to update you on my progress, or lack thereof. I have run your code exactly as you provided it with 2 exceptions. I modified the baud rates to 115200 for the Serial monitor and 57600 for the uLCD. All I receive is an endless output of NACK's.
              I did test this using Arduino Mega with the same baud rate as what you are using and I am receiving the correct ACK. Do you have anything else wired up on your Arduino? I did try to enlarge the size of the strings to see if it does affect the transmission and it seems that this is what results to some NACK's.
              Here are some tests in which you can have a look for reference: https://www.dropbox.com/sh/dmu2ra79e...SqXAvIF_a?dl=0.
              You need to adjust the waiting period for sending each command, otherwise implement a better routine to handle these issues.

              Best Regards,
              Kevin
              Last edited by John Kevin; 10 January 2020, 11:16 AM.

              Comment

              Working...
              X