Pytrack RMC message



  • I was playing with the Pytrack and needed the date/time from the GPS. The $GNRMC string provides the time, date, speed and direction information along with the coordinates.
    So I created a quick hack by adding this to the L76GNSS.py code. I only use date and time.

    # date time
    	def datetime(self, debug=False):
    		thetime, debug_timeout = None, False
    		if self.timeout != None:
    			self.chrono.start()
    		nmea = b''
    		while True:
    			if self.timeout != None and self.chrono.read() >= self.timeout:
    				self.chrono.stop()
    				chrono_timeout = self.chrono.read()
    				self.chrono.reset()
    				self.timeout_status = False
    				debug_timeout = True
    			if self.timeout_status != True:
    				gc.collect()
    				break
    			nmea += self._read().lstrip(b'\n\n').rstrip(b'\n\n')
    			gnrmc_idx = nmea.find(b'GNRMC') # find time data long lat
    			if gnrmc_idx >= 0:
    				gnrmc = nmea[gnrmc_idx:]
    				e_idx = gnrmc.find(b'\r\n')
    				if e_idx >= 0:
    					try:
    						gnrmc = gnrmc[:e_idx].decode('ascii')
    						gnrmc_s = gnrmc.split(',')
    						thetime = (gnrmc_s[1],gnrmc_s[9]) #return time and date
    					except Exception:
    						pass
    					finally:
    						nmea = nmea[(gnrmc_idx + e_idx):]
    						gc.collect()
    						break
    			else:
    				gc.collect()
    				if len(nmea) > 4096:
    					nmea = b''
    			time.sleep(0.1)
    		self.timeout_status = True
    		if debug and debug_timeout:
    			print('GPS timed out after %f seconds' % (chrono_timeout))
    			return(None)
    		else:
    			return(thetime)
    


  • @urblau said in Pytrack RMC message:

    gc.mem_free() <= 25000

    why do you reset device under 25K free mem?
    And you should analyze where you consume memory.

    My pytrack work many days and collect and then send data to the server.

    You must carefully manage strings and make calculations.
    e.g. previously i have used some implementation from internet about HMC5883L
    but when i saw how it eat memory on every run i go into optimized solution.
    maybe this point you to some direction:
    https://github.com/pycom/pycom-libraries/pull/8/files

    sometimes python syntax is evil in limited memory world..



  • this is my solution.....
    works quite well , but somtimes i get an memory error....

    from machine import Timer
    import time
    import gc
    import binascii
    import machine

    class L76GNSS:

    GPS_I2CADDR = const(0x10)
    
    def __init__(self, pytrack=None, sda='P22', scl='P21', timeout=None):
        if pytrack is not None:
            self.i2c = pytrack.i2c
        else:
            from machine import I2C
            self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl))
    
        self.chrono = Timer.Chrono()
    
        self.timeout = timeout
        self.timeout_status = True
    
        self.reg = bytearray(1)
        self.i2c.writeto(GPS_I2CADDR, self.reg)
    
    def _read(self):
        self.reg = self.i2c.readfrom(GPS_I2CADDR, 64)
        return self.reg
    
    def _convert_coords(self, gngll_s):
        gc.collect()
        #lat = gngll_s[1]
        lat = gngll_s[3]
        lat_d = (float(lat) // 100) + ((float(lat) % 100) / 60)
        #lon = gngll_s[3]
        lon = gngll_s[5]
        lon_d = (float(lon) // 100) + ((float(lon) % 100) / 60)
        #if gngll_s[2] == 'S':
        if gngll_s[4] == 'S':
            lat_d *= -1
        #if gngll_s[4] == 'W':
        if gngll_s[6] == 'W':
            lon_d *= -1
        #zeit = gngll_s[5]
        zeit = gngll_s[1]
        #print("zeit", zeit)
        geschw = gngll_s[7]
        kurs = gngll_s[8]
        datum = gngll_s[9]
        return(lat_d, lon_d, zeit, datum, geschw, kurs)
    
    def coordinates(self, debug=False):
        lat_d, lon_d, zeit, datum, geschw, kurs, debug_timeout = None, None, None, None, None, None, False
        if self.timeout != None:
            self.chrono.reset()
            self.chrono.start()
        nmea = b''
        while True:
            if self.timeout != None and self.chrono.read() >= self.timeout:
                self.chrono.stop()
                chrono_timeout = self.chrono.read()
                self.chrono.reset()
                self.timeout_status = False
                debug_timeout = True
            if self.timeout_status != True:
                gc.collect()
                break
            gc.collect()#######################################################
            if gc.mem_free() <= 25000:#########################################
                print('##############################################################test1 %f' % (gc.mem_free()))##############################
                machine.reset()################################################
    
            nmea += self._read().lstrip(b'\n\n').rstrip(b'\n\n')
            #gngll_idx = nmea.find(b'GNGLL')
            #print (nmea)
            gngll_idx = nmea.find(b'GNRMC')
            if gngll_idx >= 0:
                gngll = nmea[gngll_idx:]
                e_idx = gngll.find(b'\r\n')
                if e_idx >= 0:
                    try:
                        gngll = gngll[:e_idx].decode('ascii')
                        gngll_s = gngll.split(',')
                        #print("gngll_s", gngll_s)
                        lat_d, lon_d, zeit, datum, geschw, kurs = self._convert_coords(gngll_s)
                    except Exception:
                        pass
                    finally:
                        nmea = nmea[(gngll_idx + e_idx):]
                        gc.collect()
                        break
            else:
                gc.collect()
                if len(nmea) > 4096:
                    nmea = b''
            time.sleep(0.1)
        self.timeout_status = True
        if debug and debug_timeout:
            print('GPS timed out after %f seconds' % (chrono_timeout))
            return(None, None, None, None, None, None)
        else:
            gc.collect()
            return(lat_d, lon_d, zeit, datum, geschw, kurs)


  • @ozeta
    you can get IndexError in various places if message is somehow malformed.



  • @livius hi, yesterday i figured it out and did this change on my own.

    as for error handling what do you refer to? i didn't have any trouble till today



  • @ozeta
    Simply add something like this on the list:

     'GNGLL': gpgll
    

    and other commands. As you can see i attache GNGLL to already supported gpgll emthod



  • @livius hi, cannot code right now but i have some questions: what are glonass sentences?

    i see that micropygps uses:
    'GPRMC', 'GPGGA', 'GPVTG', 'GPGSA', 'GPGSV', 'GPGLL'

    from l76 documentation ( here: http://ecksteinimg.de/Datasheet/QuectelL76-LGNSS.pdf )
    gnsll fix uses:
    GPGSV, GLGSV, GNGLL, GNGSA
    in this list, oly gpgsv is implemented in micropyGPS. I can simply add and implement these other 3?



  • Thanks, I'll give it a try. Looks good!



  • @rolandvs
    better is usuing some working code which exist on the web
    the best i have found is this:
    https://github.com/inmcm/micropyGPS/blob/master/micropyGPS.py

    it need some modifications and extend error handling.
    Also at the end you need to add GLONASS comands to the list.
    Work for me like a charm :)


Log in to reply
 

Pycom on Twitter