Shop OBEX P1 Docs P2 Docs Learn Events
GPS_SmartMode — Parallax Forums

GPS_SmartMode

Chuck RiceChuck Rice Posts: 210
edited 2008-03-03 18:58 in Propeller 1
I am trying to use the GPS_SmartMode object. It works, but the Parallax GPS module is supposed to update about once a second. But to read all of the information, it ends up taking 10 to 12 seconds.

Pub getGPSdata

  GPS.GetInfo(@hwString, @fwString)
  GPS.GetDateAndTime(@date_string, @time_string)

  valid     := GPS.GetValid
  satellites:= GPS.GetSats
  latitude  := GPS.GetLatitude
  longitude := GPS.GetLongitude
  altitude  := GPS.GetAltitude
  speed     := GPS.GetSpeed
  heading   := GPS.GetHeading





Is this a limit of the Object, or of the GPS module's smart mode. Do I have to go to RAW mode to get true 1Hz data? -Chuck-

Comments

  • PerryPerry Posts: 253
    edited 2008-02-21 02:14
    The Smart Mode Object does to much I/O, every request requires TX of command, followed by RX of data.

    You should use the "dumb mode" which only listens.

    Here is may latest version, there should be only minor changes needed for the Parallax module

    Perry
  • Chuck RiceChuck Rice Posts: 210
    edited 2008-02-21 02:45
    Thanks! I thought I would have to write code to read the raw data. Your code looks like exactly what I needed. -Chuck-
  • JasonEJasonE Posts: 16
    edited 2008-02-22 16:22
    Chuck,

    Did you happen to try the posted code on the Parallax GPS module? Did it work straight away, or did you have to modify it at all?

    Thanks,

    Jason
  • Chuck RiceChuck Rice Posts: 210
    edited 2008-02-29 00:32
    I did get the Parallax GPS object to work, but it was really slow.

    The RAW-mode version works much faster. I have modified it a bit, but just to
    add some comments and new calls. I am having trouble with the date though.
    It always returns 0000000. Everything else seems to work. Here is a picture of it
    running:RobotGPS.JPG The GPS
    is running on one propboard, and sending the output to a second propboard
    via a serial link for display. I am still in the middle of testing it, but here is the
    code I use to call it:


      GPS.start 
    
      serial.tx(cCR)                                          
    
      repeat 
        loopStartCnt := cnt
        serial.tx(cClear)                                     
    
        serial.str(string("FixQuality: "))
        serial.str(GPS.FixQuality)
        serial.tx(cCR)                                         
        
        serial.str(string("  altitude: "))
        serial.str(GPS.altitude)
        serial.tx(cCR)                                          
        serial.str(string("     speed: "))
        serial.dec(GPS.speed)
        serial.tx(cCR)                                          
        serial.str(string("   heading: "))
        serial.dec(GPS.heading)
        serial.tx(cCR)                                          
        
        serial.str(string("      time: "))
        serial.str(GPS.time)
        serial.tx(cCR)                                          
        serial.str(string("      date: "))
        serial.hex(GPS.date,12)
        serial.tx(cCR)                                          
        
        serial.str(string("       lat: "))
        serial.str(GPS.latitude)
        serial.tx(" ")                                     
        serial.str(GPS.N_S)
        serial.tx(cCR)                                          
        serial.str(string("      long: "))
        serial.str(GPS.longitude)
        serial.tx(" ")                                     
        serial.str(GPS.E_W)
        serial.tx(cCR)                                         
    
       if  GPS.satelliteCount > 0  
          serial.str(string("sats: "))
          serial.dec(GPS.satelliteCount)
          serial.tx(cCR)                                          
    
          serial.str(string("  ids: "))
          repeat i from 1 to GPS.satelliteCount
            serial.str(GPS.sat_id (i))
            serial.tx(" ")                                          
            serial.tx(" ")                                          
          serial.tx(cCR)                                          
        
          serial.str(string(" elev: "))
          repeat i from 1 to GPS.satelliteCount
            serial.str(GPS.sat_elevation (i))
            serial.tx(" ")                                          
            serial.tx(" ")
          serial.tx(cCR)                                          
    
          serial.str(string("   az:"))
          repeat i from 1 to GPS.satelliteCount
            serial.str(GPS.sat_azimuth (i))
            serial.tx(" ")                                          
          serial.tx(cCR)                                          
    
          serial.str(string("  snr: "))
          repeat i from 1 to GPS.satelliteCount
            serial.str(GPS.sat_snr (i))
            serial.tx(" ")                                          
            serial.tx(" ")                                          
          serial.tx(cCR)                                          
        
       waitcnt(Cnt+(clkfreq*1))                                               
      
    
    
    



    Thanks to Perry for getting me started!

    BTW Perry, what is RMC_Ready? It is always one, so I deleted it. -Chuck-
  • PerryPerry Posts: 253
    edited 2008-02-29 03:37
    I was going to suggest upping the baud rate, but the Paralax module only runs at 4800 baud.

    GPSready inicates that all 3 sat position rmc messages have been seen. used on an ovehead sat view (the mini version does not include this).

    nearly every thing returned is a string in my code what is with date as "serial.hex(GPS.date,12)"

    Perry
  • Chuck RiceChuck Rice Posts: 210
    edited 2008-02-29 04:16
    With your code, speed is no longer a problem. I get all the data at a 1Hz rate. The time field updates every second.


    When I try displaying date as a string, I get a null string. To verify that it was a zero length string, I changed to display it as hex.

    All three RMC messages? I thought that there was only 1 RMC sentence, but three GSV messages. I may be misunderstanding something.

    I tried to attach my edited version of GPS_IO_full.spin, but I get an error trying to attach it. -Chuck-
  • PerryPerry Posts: 253
    edited 2008-03-01 20:40
    Sorry, ready was supposed to show that all GSV messages had been received.

    My suspicion is that you should allocate 80 bytes for the rmc sentence.
    The parallax module seems to output a little extra than the SIRF module I use.

    It looks like there is still a bug in my code

    Perry
  • Chuck RiceChuck Rice Posts: 210
    edited 2008-03-01 21:04
    Thanks. I think that it needs to be 82 bytes if I am reading the correct nema section:
    NEMA said...
    Under the NMEA-0183 standard, all characters used are printable
    ASCII text (plus carriage return and line feed). NMEA-0183 data
    is sent at 4800 baud.

    The data is transmitted in the form of "sentences". Each
    sentence starts with a "$", a two letter "talker ID", a three
    letter "sentence ID", followed by a number of data fields
    separated by commas, and terminated by an optional checksum, and
    a carriage return/line feed. A sentence may contain up to 82
    characters including the "$" and CR/LF

    I tried giving all sentences 90 bytes and I changed the two limit checks to 82, but no joy.


    I think I need to dump the raw sentence. -Chuck-
  • Chuck RiceChuck Rice Posts: 210
    edited 2008-03-01 22:03
    The date is there in the record, but it is followed by three commas. I think that the code that handles the ,,, (null values) is causing the problem. -Chuck-
  • Chuck RiceChuck Rice Posts: 210
    edited 2008-03-01 23:16
    I found several problems and fixed them. The test for the "A" in the RMC
    statement was off by two for my GPS. I only get HHMMSS not HHMMSS.SS
    The extra three characters (".SS") Were causing the test to be wrong.

    also I added a cptr-- to remove the checksum "*" from the last field. The
    star was showing up in the last field.

    I also removed the code that tested for the doubled commas. You had
    already replaced the comma with a null and that was sufficient to
    terminate the null string.

    I will post the modified code in the text since I get an error when I try
    to attach it to this post.

    '' *****************************
    ''
    '' Raw mode GPS routines
    ''
    '' *****************************
    CON
    
       CR = 13                              ' ASCII <CR>
       LF = 10                              ' ASCII <LF>
    
       serRecv   = 8                      ' Serial Receive
       
    VAR 
       long gps_stack[noparse][[/noparse]22]
        
       byte GP_RMC_b  [noparse][[/noparse]90], GP_GGA_b [noparse][[/noparse]90], GP_GSA_b [noparse][[/noparse]90]   
       long GP_RMC_a  [noparse][[/noparse]20], GP_GGA_a [noparse][[/noparse]20], GP_GSA_a [noparse][[/noparse]20]
       
       byte GP_GSV_1b [noparse][[/noparse]90], GP_GSV_2b[noparse][[/noparse]90], GP_GSV_3b[noparse][[/noparse]90]   
       long GP_GSV_1a [noparse][[/noparse]20], GP_GSV_2a[noparse][[/noparse]20], GP_GSV_3a[noparse][[/noparse]20]
       
       byte gps_buff[noparse][[/noparse]90],Rx,chk_xsum,chk_xval
       long cog,cptr,ptr,arg,j
       long Null
       long rmc_ready
         
    OBJ
      uart : "HITT_Serial_Recv_Buffer_True_32"
    
    PUB start : okay
    
    '' Starts uart object (at baud specified) in a cog
    '' -- returns false if no cog available
    
    '   okay := uart.start(14,4800) ' (serRecv,serXmit,0,4800)
        okay := uart.Init (serRecv,4800)
        return cog := cognew(readNEMA,@gps_stack) + 1 
    
    pri readNEMA
    
    Null[noparse][[/noparse]0] := rmc_ready := 0
    
    repeat
      longfill(gps_buff,20,0)
    
      repeat while Rx <> "$"        ' wait for the $ to insure we are starting with
         Rx := uart.Rx              '   a complete NMEA sentence 
    
      cptr     := 0
      chk_xsum := 0
      
      repeat while Rx <> "*"        '  continue to collect data until the end of the NMEA sentence 
         Rx := uart.Rx
                      
         if Rx == ","
           gps_buff[noparse][[/noparse]cptr++] := 0    '  Replace the character
         else
           gps_buff[noparse][[/noparse]cptr++] := Rx   '  Save the character 
    
         if cptr > 82
           quit
    
         if Rx <> "*"
          chk_xsum ^= Rx                                                                                                       
    
      cptr--
          
      chk_xval := to_hex(uart.Rx) << 4
      chk_xval += to_hex(uart.Rx)
      
      if chk_xsum == chk_xval
        
       if gps_buff == "R"
         if gps_buff == "M"
           if gps_buff == "C"
              rmc_ready := 0
              copy_buffer(@GP_RMC_b, @GP_RMC_a)
                    
       if gps_buff == "G"
         if gps_buff == "G"  
           if gps_buff == "A"
               copy_buffer(@GP_GGA_b, @GP_GGA_a)
    
       if gps_buff == "G"
         if gps_buff == "S"
           if gps_buff == "A"
               copy_buffer(@GP_GSA_b, @GP_GSA_a)
               
       if gps_buff == "G"
         if gps_buff == "S"
           if gps_buff == "V"       
             if gps_buff[noparse][[/noparse]8] == "1"
                   copy_buffer(@GP_GSV_1b, @GP_GSV_1a)               
             if gps_buff[noparse][[/noparse]8] == "2"
                   copy_buffer(@GP_GSV_2b, @GP_GSV_2a)               
             if gps_buff[noparse][[/noparse]8] == "3"
                   copy_buffer(@GP_GSV_3b, @GP_GSV_3a)
           rmc_ready := 1
                   
    pri copy_buffer ( buffer,args)
             bytemove(buffer,@gps_buff,cptr)
             ptr := buffer
             arg := 0
             repeat j from 0 to 82
              if arg > 19
                quit
     
              if byte[noparse][[/noparse]ptr] == 0
                 long[noparse][[/noparse]args][noparse][[/noparse]arg++] := ptr+1
              ptr++
              
    
    pri to_hex(key)
    
      case key
       "0": return 0
       "1": return 1
       "2": return 2
       "3": return 3 
       "4": return 4
       "5": return 5
       "6": return 6
       "7": return 7
       "8": return 8
       "9": return 9
       "A": return 10
       "B": return 11
       "C": return 12
       "D": return 13
       "E": return 14
       "F": return 15
                 
    pri xsum
       return chk_xsum
       
    pri xval
       return chk_xval
       
    pub altitude
    
    '' Altitude, Meters, above mean sea level
    
       return GP_GGA_a[noparse][[/noparse]8]
       
    pub speed
    
    '' Speed over the ground in knots
    
       return GP_RMC_a[noparse][[/noparse]6]
    
    pub heading
    
    '' Track angle in degrees True
    
       return GP_RMC_a[noparse][[/noparse]7]
    
    pub time
    
    '' UTC time of fix HHMMSS
    
       return GP_GGA_a[noparse][[/noparse]0]
       
    pub date
    
    '' DDMMYY
    
       return GP_RMC_a[noparse][[/noparse]8]
        
    pub latitude
    
    '' degrees and minutes - dddmm.mmmm 
    
       return GP_GGA_a
        
    pub N_S
    
    '' N = north or S = south 
    
       return GP_GGA_a
         
    pub longitude
    
    '' degrees and minutes - dddmm.mmmm 
    
       return GP_GGA_a
        
    pub E_W
    
    '' E = east or W = west 
    
       return GP_GGA_a
    
    pub FixQuality
    
    {{ 
        0 = invalid
        1 = GPS fix (SPS)
        2 = DGPS fix
        3 = PPS fix
        4 = Real Time Kinematic
        5 = Float RTK
        6 = estimated (dead reckoning) (2.3 feature)
        7 = Manual input mode
        8 = Simulation mode
    }}
       return GP_GGA_a
    
    pub satellites
    
    '' Number of satellites being tracked (returns String)
    
       return GP_GGA_a[noparse][[/noparse]6]
      
    pub satelliteCount | n
    
    '' Number of satellites being tracked (returns a number)
         
        n := to_hex(byte[noparse][[/noparse]GP_GGA_a[noparse][[/noparse]6]][noparse][[/noparse]0]) *10   'uses existing hex lookup as a decimal lookup
        n += to_hex(byte[noparse][[/noparse]GP_GGA_a[noparse][[/noparse]6]])
    
       return n
      
    pub hdop
       return GP_GGA_a[noparse][[/noparse]7]
       
    pub vdop
       return GP_GSA_a[noparse][[/noparse]14]
    
    pub ready
       return rmc_ready
    
    pub sat_id (sat)
    
    '' Ranges from 1 to 32
    
        case sat
          1:
              return GP_GSV_1a
          2:
              return GP_GSV_1a[noparse][[/noparse]7]
          3:
              return GP_GSV_1a[noparse][[/noparse]11]
          4:
              return GP_GSV_1a[noparse][[/noparse]15]
          5:
              return GP_GSV_2a
          6:
              return GP_GSV_2a[noparse][[/noparse]7]
          7:
              return GP_GSV_2a[noparse][[/noparse]11]
          8:
              return GP_GSV_2a[noparse][[/noparse]15]
          9:
              return GP_GSV_3a
          10:
              return GP_GSV_3a[noparse][[/noparse]7]
          11:
              return GP_GSV_3a[noparse][[/noparse]11]
          12:
              return GP_GSV_3a[noparse][[/noparse]15]
          other:
              return 0
              
    pub sat_elevation (sat)
    
    '' Ranges from 0 to 90
    
        case sat
          1:
              return GP_GSV_1a
          2:
              return GP_GSV_1a[noparse][[/noparse]8]
          3:
              return GP_GSV_1a[noparse][[/noparse]12]
          4:
              return GP_GSV_1a[noparse][[/noparse]16]
          5:
              return GP_GSV_2a
          6:
              return GP_GSV_2a[noparse][[/noparse]8]
          7:
              return GP_GSV_2a[noparse][[/noparse]12]
          8:
              return GP_GSV_2a[noparse][[/noparse]16]
          9:
              return GP_GSV_3a
          10:
              return GP_GSV_3a[noparse][[/noparse]8]
          11:
              return GP_GSV_3a[noparse][[/noparse]12]
          12:
              return GP_GSV_3a[noparse][[/noparse]16]
          other:
              return 0
              
    pub sat_azimuth (sat)
    
    '' True, Range 0 to 359
    
        case sat
          1:
              return GP_GSV_1a
          2:
              return GP_GSV_1a[noparse][[/noparse]9]
          3:
              return GP_GSV_1a[noparse][[/noparse]13]
          4:
              return GP_GSV_1a[noparse][[/noparse]17]
          5:
              return GP_GSV_2a
          6:
              return GP_GSV_2a[noparse][[/noparse]9]
          7:
              return GP_GSV_2a[noparse][[/noparse]13]
          8:
              return GP_GSV_2a[noparse][[/noparse]17]
          9:
              return GP_GSV_3a
          10:
              return GP_GSV_3a[noparse][[/noparse]9]
          11:
              return GP_GSV_3a[noparse][[/noparse]13]
          12:
              return GP_GSV_3a[noparse][[/noparse]17]
          other:
              return 0         
    
    pub sat_snr (sat)
    
    '' Range 0 to 99, null when not tracking
    
        case sat
          1:
              return GP_GSV_1a[noparse][[/noparse]6]
          2:
              return GP_GSV_1a[noparse][[/noparse]10]
          3:
              return GP_GSV_1a[noparse][[/noparse]14]
          4:
              return GP_GSV_1a[noparse][[/noparse]18]
          5:
              return GP_GSV_2a[noparse][[/noparse]6]
          6:
              return GP_GSV_2a[noparse][[/noparse]10]
          7:
              return GP_GSV_2a[noparse][[/noparse]14]
          8:
              return GP_GSV_2a[noparse][[/noparse]18]
          9:
              return GP_GSV_3a[noparse][[/noparse]6]
          10:
              return GP_GSV_3a[noparse][[/noparse]10]
          11:
              return GP_GSV_3a[noparse][[/noparse]14]
          12:
              return GP_GSV_3a[noparse][[/noparse]18]
          other:
              return 0
    
    



    Thanks for giving me a good start. Your code saved me a lot of time
    and it was interesting. You might want to post it in the object exchange.
    -Chuck-
  • Chuck RiceChuck Rice Posts: 210
    edited 2008-03-03 00:58
    Noticed another possible problem. I have not fixed it, so I am not sure
    if it will help or hurt.

    the longfill(gps_buff,0,20)
    may need to be changed to longfill(gps_buff,20,0)

    From the manual: LONGFILL(StartAddress, Value, Count )

    it looks like the value and count are swapped. This causes the buffer
    not to be zeroed, but I am not sure it needs to be as it seems to work
    as is. -Chuck-
  • PerryPerry Posts: 253
    edited 2008-03-03 13:31
    Every version of the code I have shows "longfill(gps_buff,20,0)".
    Even the code you quoted above shows the same.

    This code, in mini version is in the object exchange obex.parallax.com/objects/225/

    Perry
  • Chuck RiceChuck Rice Posts: 210
    edited 2008-03-03 18:22
    Perry said...
    Every version of the code I have shows "longfill(gps_buff,20,0)".

    Yikes! I got it backwards too. The format is value,count.

    "longfill(gps_buff,20,0)" says to put the value 20 into gps_buff zero times. Sorry for the confusion. -Chuck-
  • PerryPerry Posts: 253
    edited 2008-03-03 18:58
    After some testing and thought, I think that should have been: "longfill(@gps_buff,0,20)"

    Perry
Sign In or Register to comment.