Skip to content

Commit def82be

Browse files
committed
Prior to improving error handling.
1 parent 3a7c7c7 commit def82be

File tree

5 files changed

+47
-14
lines changed

5 files changed

+47
-14
lines changed

TUTORIAL.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,11 @@ The mechanism works because the device driver (written in C) implements the
10781078
following methods: `ioctl`, `read`, `write`, `readline` and `close`. See
10791079
section 5.3 for further discussion.
10801080

1081+
Applications using the UART should be designed such that all coros minimise
1082+
blocking periods. This is because blocking while the UART is receiving data can
1083+
lead to buffer overflows with consequent loss of data. This can be ameliorated
1084+
by using a larger UART read buffer length or a lower baudrate.
1085+
10811086
### 5.1.1 A UART driver example
10821087

10831088
The program `auart_hd.py` illustrates a method of communicating with a half

gps/README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,12 @@ and subsequent characters are stripped from the last. Thus if the string
398398
was received `reparse` would see
399399
`['GPGGA','123519','4807.038','N','01131.000','E','1','08','0.9','545.4','M','46.9','M','','']`
400400

401+
## 2.6 Public class variable
402+
403+
* `FULL_CHECK` Default `True`. If set `False` disables CRC checking and other
404+
basic checks on received sentences. This is intended for use at high baudrates
405+
where the time consumed by these checks can be excessive.
406+
401407
# 3. The GPS class read-write driver
402408

403409
This is a subclass of `AS_GPS` and supports all its public methods, coroutines
@@ -538,9 +544,10 @@ Under investigation. **
538544

539545
Further, there are problems (at least with my GPS firmware build
540546
['AXN_2.31_3339_13101700', '5632', 'PA6H', '1.0']) whereby setting baudrates
541-
only works for certain rates. 19200, 38400 and 115200 work. 4800 sets 115200.
542-
Importantly 9600 does nothing. This means that the only way to restore the
543-
default is to perform a `FULL_COLD_START`. The test programs do this.
547+
only works for certain rates. 19200, 38400, 57600 and 115200 work. 4800
548+
sets 115200. Importantly 9600 does nothing. This means that the only way to
549+
restore the default is to perform a `FULL_COLD_START`. The test programs do
550+
this.
544551

545552
If you change the GPS baudrate the UART should be re-initialised immediately
546553
after the `baudrate` coroutine terminates:

gps/as_GPS.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,20 +171,21 @@ def __init__(self, sreader, local_offset=0, fix_cb=lambda *_ : None, cb_mask=RMC
171171
self._valid = 0 # Bitfield of received sentences
172172
if sreader is not None: # Running with UART data
173173
loop = asyncio.get_event_loop()
174-
loop.create_task(self._run())
174+
loop.create_task(self._run(loop))
175175

176176
##########################################
177177
# Data Stream Handler Functions
178178
##########################################
179179

180-
async def _run(self):
180+
async def _run(self, loop):
181181
while True:
182182
res = await self._sreader.readline()
183183
try:
184184
res = res.decode('utf8')
185185
except UnicodeError: # Garbage: can happen e.g. on baudrate change
186186
continue
187-
self._update(res)
187+
loop.create_task(self._update(res))
188+
await asyncio.sleep_ms(0) # Ensure task runs and res is copied
188189

189190
# Update takes a line of text
190191
def _update(self, line):
@@ -195,21 +196,26 @@ def _update(self, line):
195196
return None # Bad character received
196197
except StopIteration:
197198
pass # All good
198-
199+
await asyncio.sleep_ms(0)
199200
if len(line) > self._SENTENCE_LIMIT or not '*' in line:
200201
return None # Too long or malformed
201202

202203
a = line.split(',')
203204
segs = a[:-1] + a[-1].split('*')
205+
await asyncio.sleep_ms(0)
206+
204207
if self.FULL_CHECK: # 6ms on Pyboard
205208
if not self._crc_check(line, segs[-1]):
206209
self.crc_fails += 1 # Update statistics
207210
return None
211+
await asyncio.sleep_ms(0)
212+
208213
self.clean_sentences += 1 # Sentence is good but unparsed.
209214
segs[0] = segs[0][1:] # discard $
210215
segs = segs[:-1] # and checksum
211216
if segs[0] in self.supported_sentences:
212-
s_type = self.supported_sentences[segs[0]](segs)
217+
s_type = self.supported_sentences[segs[0]](segs) # Parse
218+
await asyncio.sleep_ms(0)
213219
if isinstance(s_type, int) and (s_type & self.cb_mask):
214220
# Successfully parsed, data was valid and mask matches sentence type
215221
self._fix_cb(self, s_type, *self._fix_cb_args) # Run the callback

gps/as_GPS_time.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,17 @@ def time(minutes=1):
105105
loop.run_until_complete(do_time(minutes))
106106

107107
# ******** Measure accracy of μs clock ********
108+
# At 9600 baud see occasional lag of up to 3ms followed by similar lead.
109+
# This implies that the ISR is being disabled for that period (~3 chars).
110+
# SD 584μs typical.
111+
# Test produces better numbers at 57600 baud (SD 112μs)
112+
# and better still at 10Hz update rate (SD 34μs). Why??
113+
# Unsure why. Setting of .FULL_CHECK has no effect (as expected).
114+
108115
# Callback occurs in interrupt context
109116
us_acquired = None
110117
def us_cb(my_gps, tick, led):
111-
global us_acquired
118+
global us_acquired # Time of previous PPS edge in ticks_us()
112119
if us_acquired is not None:
113120
# Trigger event. Pass time between PPS measured by utime.ticks_us()
114121
tick.set(utime.ticks_diff(my_gps.acquired, us_acquired))

gps/as_rwGPS_time.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929

3030
# Avoid multiple baudrates. Tests use 9600 or 115200 only.
3131
# *** Baudrate over 19200 causes messages not to be received ***
32-
BAUDRATE = 19200
33-
UPDATE_INTERVAL = 200 # 100
34-
READ_BUF_LEN = 1000 # test
32+
BAUDRATE = 57600
33+
UPDATE_INTERVAL = 100
34+
READ_BUF_LEN = 200 # test
3535
print('Available tests:')
3636
print('calibrate(minutes=5) Set and calibrate the RTC.')
3737
print('drift(minutes=5) Repeatedly print the difference between RTC and GPS time.')
@@ -58,7 +58,7 @@ async def shutdown():
5858
#gps.close() # Stop ISR
5959
#print('Restoring default 1s update rate.')
6060
#await asyncio.sleep(0.5)
61-
#await gps.update_interval(1000) # 1s update rate **** DO WE NEED TO SET END EVENT? *****
61+
#await gps.update_interval(1000) # 1s update rate
6262
#print('Restoring satellite data.')
6363
#await gps.command(as_rwGPS.DEFAULT_SENTENCES) # Restore satellite data
6464

@@ -73,6 +73,7 @@ async def setup():
7373
gps = as_tGPS.GPS_RWTimer(sreader, swriter, pps_pin, local_offset=1,
7474
fix_cb=lambda *_: red.toggle(),
7575
pps_cb=lambda *_: blue.toggle())
76+
gps.FULL_CHECK = False
7677
await asyncio.sleep(2)
7778
await gps.baudrate(BAUDRATE)
7879
uart.init(BAUDRATE)
@@ -164,8 +165,12 @@ def time(minutes=1):
164165
loop.run_until_complete(shutdown())
165166

166167
# ******** Measure accracy of μs clock ********
168+
# Test produces better numbers at 57600 baud (SD 112μs)
169+
# and better still at 10Hz update rate (SD 34μs).
170+
# Unsure why.
171+
167172
# Callback occurs in interrupt context
168-
us_acquired = None
173+
us_acquired = None # Time of previous PPS edge in ticks_us()
169174
def us_cb(my_gps, tick, led):
170175
global us_acquired
171176
if us_acquired is not None:
@@ -185,12 +190,15 @@ async def us_setup(tick):
185190
gps = as_tGPS.GPS_RWTimer(sreader, swriter, pps_pin, local_offset=1,
186191
fix_cb=lambda *_: red.toggle(),
187192
pps_cb=us_cb, pps_cb_args=(tick, blue))
193+
gps.FULL_CHECK = False
188194
await asyncio.sleep(2)
189195
await gps.baudrate(BAUDRATE)
190196
uart.init(BAUDRATE)
191197
await asyncio.sleep(1)
192198
await gps.enable(gsa=0, gsv=0) # Disable satellite data
193199
await gps.update_interval(UPDATE_INTERVAL)
200+
pstr = 'Baudrate {} update interval {}ms satellite messages disabled.'
201+
print(pstr.format(BAUDRATE, UPDATE_INTERVAL))
194202

195203
async def do_usec(minutes):
196204
global gps

0 commit comments

Comments
 (0)