Shop OBEX P1 Docs P2 Docs Learn Events
P1 GPS Simulator — Parallax Forums

P1 GPS Simulator

pic18f2550pic18f2550 Posts: 400
edited 2022-01-27 21:33 in Propeller 1

Hello,
Is there a tool in Spin for the P1 with which I can generate GPS data for testing purposes?

Thank you.

Comments

  • I would just download ucenter from ublox that does just about everything you need to do with a GPS.

    It has a capture option that you can save to a file.

    u-center

    Mike

  • This is all the wrong direction.
    I want to create a NEMA string from defaults.

  • Attached is a program I used in teaching a robotics class. You can modify it to vary lat_min and lon_min to form whatever trajectory you wish.

    -Phil

  • A good document:

    http://freenmea.net/docs

  • Nice teaching program, Phil!

  • Okay, I can do something with that.

    What is still missing is the checksum calculation.

    hexadecimal representation of the checksum
    (The checksum is calculated by XORing all data bytes between (each excluding) the dollar sign '$' and the asterisk '*').

    Should not be a problem though.

  • You might also be able to make use of my GPSMath object posted here:

    https://forums.parallax.com/discussion/comment/1431330/#Comment_1431330

    -Phil

  • LtechLtech Posts: 380
    edited 2022-01-24 21:23

    I can't insert code?
    This is how we control crc of nmea buffer

  • LtechLtech Posts: 380
    edited 2022-02-02 14:58

    This is the format I use in a lot of NMEA translators.
    I can't still get a good layout for code ?? :s

           addToPacket(String("*"), 1)
           addToPacket(0, 1)                                                        'need to compute crcp
           addToPacket(Number.hex(crc(@gps_buff, strsize(@gps_buff)),2),2)
           addToPacket(String((cr)), strsize(String(cr)))
           addToPacket(String((lf)), strsize(String(lf)))
           addToPacket(0, 1)
    
    
    
    
    PUB crc(pBuf, buflen): crcx | i
    
          crcx:= 0
    
           repeat i from 1 to  buflen -2   '= - *
    
             crcx ^= BYTE[pBuf][i]
    
    
    
    PUB addToPacket(straddr, length) | pointer        'no zeros may be added, except at the end!
            pointer := straddr
            repeat length
                if (packetcount<256)
                     gps_buff[packetcount++] := byte[pointer++]
    
  • pic18f2550pic18f2550 Posts: 400
    edited 2022-02-02 13:37

    I did the CRC calculation with a small intermediate routine.

    pri gprmc
    '' string("$GPRMC,000000.00,A,4806.71974,N,12247.16062,W,1.235,270.53,080415,,,A*63", 13, 10)
    
      sendstr(string("$GPRMC,"))                     ''Start GPS Recommended Minimum sentence C
    
      sendstr(num.decx(gps_utc[0], 6))                ''000000.000 Fix taken at 13:24:55.970 UTC
      sendstr(string("."))
      sendstr(num.decx(gps_utc[1], 4))
      sendstr(string(","))
    
      if gps_stat=="A"                               ''Status A=Active or V=Void
        sendstr(string("A,"))
      else
        sendstr(string("V,"))
    
    ....
    
      sendstr(string(","))                          ''Magnetic Variation y
    
      sendstr(string("A*"))                         ''The checksum data, always begins with *
    
    
    PRI sendstr(stringPtr)|crc
      repeat strsize(stringPtr)
        gps.Tx(byte[stringPtr])                                                       
        case byte[stringPtr]
          "$":
            crc := 0
            stringPtr++
          "*":
            gps.str(num.decx(crc, 2))
            gps.str(string(13,10))
            stringPtr++
          other:
            crc ^= byte[stringPtr++]
    
    

    Furthermore the question arises how do I suppress leading zeros?
    num.decx(5, 4) ->> 0005

    Is there a variant where I can output floating point values to a string?

  • VonSzarvasVonSzarvas Posts: 3,448
    edited 2022-02-02 15:00

    @Ltech said:
    This is the format I use in a lot of NMEA translators.
    I can't still get a good layout for code ?? :s

           addToPacket(String("*"), 1)
           addToPacket(0, 1)                                                        'need to compute crcp
           addToPacket(Number.hex(crc(@gps_buff, strsize(@gps_buff)),2),2)
           addToPacket(String((cr)), strsize(String(cr)))
           addToPacket(String((lf)), strsize(String(lf)))
           addToPacket(0, 1)
    
    
    
    
    PUB crc(pBuf, buflen): crcx | i
    
          crcx:= 0
    
           repeat i from 1 to  buflen -2   '= - *
    
             crcx ^= BYTE[pBuf][i]
    
    
    
    PUB addToPacket(straddr, length) | pointer        'no zeros may be added, except at the end!
            pointer := straddr
            repeat length
                if (packetcount<256)
                     gps_buff[packetcount++] := byte[pointer++]
    

    Hi @Ltech !
    Click the Cog icon (top right of your post), then Edit. You will see the formatting changes I just made to your post to display code.

    In short, use 3 backticks top and bottom. And keep the first line of code on the next line after the backticks, otherwise the code preview won't appear when the forum page renders.

  • Is there a variant where I can output floating point values to a string?

    Ugh. Don't use floating point. Attached is an object I wrote (expanding on Chip and Jon's object) that allows scaled integers to be written in fixed-point format.

    -Phil

  • JonnyMacJonnyMac Posts: 9,102
    edited 2022-02-02 23:24

    In my variation of FDS there is a method called dpdec() that will take a fixed-point number (I'm will Phil on this) and insert a decimal point where you want it. If your value is 12345 and you want to output 123.45 you might do something like this:

      display.dpdec(value, 2)
    

    This will insert the decimal point before the last two digits of the value (inserting 0s if needed).

    This object also allows formatted strings, so you could do something like this

      display.fstr1(string("The temperature is %.2f"), value)
    

    The %f is for "make it look like floating point." :)

  • Spin stores the float value in a long.
    Is there a way to extend the precision by a few digits? e.g. in two longs?

    I am currently working with "FloatString.spin".
    ''*****************************************
    ''* Floating-Point <-> Strings v 1.1 *
    ''* Single-precision IEEE-754 *
    ''* Authors: Chip Gracey and Cam Thompson *
    ''* (C) 2006 Parallax, Inc. *
    ''* See end of file for terms of use. *
    ''*****************************************

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2022-02-03 19:58

    Why are you using floating point? It's so unnecessary (and inappropriate) for what you're trying to accomplish. For example, this number:

    12247.16062 (longitude)

    is just 1224716062 (which fits in a long) printed with a decimal point between the fifth and sixth digits. Both Jon and I have provided you with ways to do this.

    For example, using my Simple Numbers Plus, the above longitude can be inserted into a $GPRMS string, thus:

    bytemove(@gprms, num.decz(longitude / 100000, 5), 32 , 5))
    bytemove(@gprms, num.decz(longitude // 100000, 5), 38 , 5))
    

    assuming the decimal point is already there.

    -Phil

  • pic18f2550pic18f2550 Posts: 400
    edited 2022-02-05 12:30

    Phil Pilgrim (PhiPi)
    Of these only 9 digits are usable the 1. can only 0..2.
    But I need 12 digits, better 14.

    For floating point numbers in double long format there is no spin object.

    To the not would be also some arithmetic possible which works on double long basis. Addition, subtraction, multiplication and division are enough.
    In this case I would extend / shorten and output the decimal place.

  • But even with 12 digits, the format is ddmm.mmmmmmm (lat) or dddmm.mmmmmmm (lon). That's still only nine digits for the minutes, which can easily be separated from the degrees, and precise to 0.1855mm. I still don't see what the problem is.

    -Phil

  • The problem is that in long only 23 bits are available for the number sequence, 8 bits for the exponent and 1 bit for the sign.
    All values above 8.388.607 are error-prone because the value of the smallest digit is replaced by a 0.
    It is not only a matter of displaying GPS values, there is still a bit of calculation to be done. But that is another topic.

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2022-02-07 00:07

    The problem is that in long only 23 bits are available for the number sequence, 8 bits for the exponent and 1 bit for the sign.

    No, the problem is that you're trying to use floating point. Just don't!

    Use two longs: one for the degrees, the other for the minutes scaled up to integer values. The output and computations will be both simple and accurate. For example, the longitude:

    dddmm.mmmmmmm

    can be represented by two longs:

    ddd and mmmmmmmmm

    Each fits in a long. You don't need the decimal point to do the math -- only to output the result.

    -Phil

  • pic18f2550pic18f2550 Posts: 400
    edited 2022-02-07 11:19

    OK, I guess we were talking about something else. :#

    ddd and mmmmmmmmm would also be a possibility.
    But it would complicate all the comma-crossing arithmetic.

    Therefore, I would prefer an integer arithmetic with double longs. Because this is easier to handle.

    The output would work like this.
    - Output of the number as a string
    - shifting the lower decimal places
    - insert the decimal point

    1234567890+chr(0)+chr(0)
    12344567890+chr(0)
    123.4567890+chr(0)

Sign In or Register to comment.