[SOLVED] UART for GPS

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
ghilliesuit
Posts: 15
Joined: Fri Feb 25, 2022 2:55 am

[SOLVED] UART for GPS

Post by ghilliesuit » Fri Feb 25, 2022 3:10 am

Disclaimer - am a rookie with both micropython and UART .... and GPS :D .

Hardware include(s): Firmware: MicroPython V1.18

Software/IDE: Thonny 3.3.14 (Interpreter set to Pico) running on Pi400 (Raspberry Pi OS 64-bit)

Code: Select all

from machine import UART, Pin

# Connection to GPS
# UART_tx = Pin 8
# UART_rx = Pin 9

uart = UART(1, baudrate = 9600, tx=Pin(8), rx=Pin(9))

print(uart.read())
I receive the following response with no errors or anything:

Code: Select all

>>>none 
What am I missing? I was kind of expecting a bunch unprocessed data (documentation says it begins transmitting right away once its powered up. I apologize for my ignorance - and thank you for the help in advance.

--------------------------------------------------------------------------------------------------------------------------
SOLUTION / RESOLUTION - what I learned in case anyone else is in a similar position (first time user of both pieces)

First - when using machine's Pin (from machine import Pin) make sure you use the GP# pin designation. I was using the sequential designation (i.e. 1,2,3,...40) instead. This was a no-go. So, for me using UART1 I used GP4 and GP5 pins and addressed them as Pin(4) and Pin(5). A clue will be a "bad Tx pin" error.

Second - Tx of one device connects to the Rx of the other device. Tx of Pico connects to Rx of GPS. Tx of GPS connects to Rx of Pico.

Third - Jumping Tx to Rx of the pico allows a loopback test (see thread below for code)

Fourth - Pay the UART#. UART0 and UART1 will need to be identified when you initialize your constructor. Failure to match up your UART# and your associated Tx/Rx pins will result in "bad Tx pin" errors.
  • uart0 = UART(0, tx=(GP# for a UART0 Tx), rx=(GP# for a UARTO Rx), ... )
  • uart1 = UART(1, tx=(GP# for a UART1 Tx), rx=(GP# for a UART1 Rx), ... )
See thread below for code that worked.
Last edited by ghilliesuit on Fri Mar 04, 2022 10:52 pm, edited 3 times in total.

davef
Posts: 813
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: UART for GPS

Post by davef » Fri Feb 25, 2022 7:06 am

Try adding in bits, parity and timeout:

Code: Select all

ser = UART(1, baudrate=9600, bits=8, parity=None, stop=1, rx=, tx=, timeout=300)
A useful UART debugging technique is to do a loopback test. Connect TX and RX send some data and watch it get displayed while running rshell etc. I don't which pins the Pico uses.

Shards
Posts: 39
Joined: Fri Jun 25, 2021 5:14 pm
Location: Milton Keynes, UK

Re: UART for GPS

Post by Shards » Fri Feb 25, 2022 3:19 pm

I've used quite a few GPS boards though not your Adafruit one. And, yes,
GPS boards usually produce a deluge of NMEA data when connected to a serial port. The default baudrate is 9600 for all the GPS boards I've tried. It's rare to need anything other than default stop bits and parity.

However, I'd agree with the last post in that it's worth checking you have a working serial connection first. Also don't forget that it's TX to RX and vise versa. Worth swapping them as a test if things don't work.

I'd also put your uart.read() in a loop:

Code: Select all

While True:
    if uart.any():
        print(uart.read())
The gps only sends in bursts, most of the time it sends nothing.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: UART for GPS

Post by pythoncoder » Sat Feb 26, 2022 1:49 pm

A GPS sends data in NMEA sentences which end in a newline, so the UART .readline() method is the way to read it (when .any() returns > 0).

There are at least two existing GPS libraries: asynchronous and synchronous. These have been tested with the Adafruit board.
Peter Hinch
Index to my micropython libraries.

ghilliesuit
Posts: 15
Joined: Fri Feb 25, 2022 2:55 am

Re: UART for GPS

Post by ghilliesuit » Sat Feb 26, 2022 4:43 pm

davef wrote:
Fri Feb 25, 2022 7:06 am
Try adding in bits, parity and timeout:

Code: Select all

ser = UART(1, baudrate=9600, bits=8, parity=None, stop=1, rx=, tx=, timeout=300)
A useful UART debugging technique is to do a loopback test. Connect TX and RX send some data and watch it get displayed while running rshell etc. I don't which pins the Pico uses.
Will do.

Once I loop them I'll use uart.write('8bitsofdata'). Then I should expect to see it in the shell? or would I need to uart.read() verify the transmission?
Shards wrote:
Fri Feb 25, 2022 3:19 pm
I've used quite a few GPS boards though not your Adafruit one. And, yes,
GPS boards usually produce a deluge of NMEA data when connected to a serial port. The default baudrate is 9600 for all the GPS boards I've tried. It's rare to need anything other than default stop bits and parity.

However, I'd agree with the last post in that it's worth checking you have a working serial connection first. Also don't forget that it's TX to RX and vise versa. Worth swapping them as a test if things don't work.

I'd also put your uart.read() in a loop:

Code: Select all

While True:
    if uart.any():
        print(uart.read())
The gps only sends in bursts, most of the time it sends nothing.
I did triple check that I am Tx to Rx and Rx to Tx from Pico to GPS. Tried switching them to Tx to Tx to see if maybe the breakout was labeled incorrectly - no luck.
pythoncoder wrote:
Sat Feb 26, 2022 1:49 pm
A GPS sends data in NMEA sentences which end in a newline, so the UART .readline() method is the way to read it (when .any() returns > 0).

There are at least two existing GPS libraries: asynchronous and synchronous. These have been tested with the Adafruit board.
Can I use either library? Do you believe one is easier to get started with? I appreciate the help! Also, I'll swtich to readline() command.

davef
Posts: 813
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: UART for GPS

Post by davef » Sat Feb 26, 2022 8:08 pm

Code: Select all

     #  do a loop-back test first

        msg = 'Test'
        ser.write(msg)
        print ('message written')

        while True:
            new_msg = ser.read()
            if not  new_msg:
                break

        print (new_msg + '\n')
Then start the program in repl, CTRL-D and ...

ghilliesuit
Posts: 15
Joined: Fri Feb 25, 2022 2:55 am

Re: UART for GPS

Post by ghilliesuit » Sat Feb 26, 2022 10:43 pm

davef wrote:
Sat Feb 26, 2022 8:08 pm
....
Then start the program in repl, CTRL-D and ...
@davef Thanks. I realized I was making an error addressing the pins. I was going by their sequential order - when Pin requires that I go by their GP#. So that is corrected in the code. Also, I changed breadboards and removed everything but the jumper wire from Tx-Rx. GP4-GP5.

I used the following code:

Code: Select all

from machine import Pin, UART
import time
uart1= UART(1, parity=None, tx=Pin(4), rx=Pin(5))

#  do a loop-back test first

msg = 'Test'
uart1.write(msg)
print ('message written')

while True:
    new_msg = uart1.readline()
    if not  new_msg:
        break

print (new_msg)
And got the following REPL output:

Code: Select all

MicroPython v1.18 on 2022-01-17; Raspberry Pi Pico with RP2040
Type "help()" for more information.
>>> %Run -c $EDITOR_CONTENT
message written
None
Ran this with the same output:

Code: Select all

from machine import Pin, UART
import time
uart1= UART(1, baudrate=9600, bits=8, parity=None, stop=1, tx=Pin(4), rx=Pin(5), timeout=300)

#  do a loop-back test first

msg = 'Test'
uart1.write(msg)
print ('message written')
while True:
    new_msg = uart1.readline()
    if not  new_msg:
        break
print (new_msg)

Still kinda scratching my head. I appreciate the help.

ghilliesuit
Posts: 15
Joined: Fri Feb 25, 2022 2:55 am

Re: UART for GPS

Post by ghilliesuit » Sat Feb 26, 2022 10:59 pm

@davef

ran the following:

Code: Select all

from machine import Pin, UART
import time
uart1= UART(1, baudrate=9600, bits=8, parity=None, stop=1, tx=Pin(4), rx=Pin(5), timeout=300)

#  do a loop-back test first

msg = 'Test'
uart1.write(msg)
print ('message written')
while True:
    uart1.write(msg)
    new_msg = uart1.readline()
    print (new_msg)
Looks like that works because I got the following REPL output:

Code: Select all

MicroPython v1.18 on 2022-01-17; Raspberry Pi Pico with RP2040
Type "help()" for more information.
>>> %Run -c $EDITOR_CONTENT
message written
b'TestTest'
b'Test'
b'Test'
b'Test'
b'Test'

davef
Posts: 813
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: UART for GPS

Post by davef » Sun Feb 27, 2022 12:36 am

Sorry, it looks like I didn't get the indentation correct. It was all commented out in my code and when I removed the # I got the last line wrong.

Puzzled about the:

Code: Select all

b'TestTest'
possibly you need to break out of the loop after printing the message.

However, how does the GPS stuff look like now?

ghilliesuit
Posts: 15
Joined: Fri Feb 25, 2022 2:55 am

Re: UART for GPS

Post by ghilliesuit » Sun Feb 27, 2022 12:51 am

davef wrote:
Sun Feb 27, 2022 12:36 am
Sorry, it looks like I didn't get the indentation correct. It was all commented out in my code and when I removed the # I got the last line wrong.

Puzzled about the:

Code: Select all

b'TestTest'
possibly you need to break out of the loop after printing the message.

However, how does the GPS stuff look like now?
I think the b'testtest' is because I had left the write('Test') in prior to entering the While loop. So the buffer (not sure if that is the right terminology) had been written to twice.

As far as the GPS - its happy now! I get the following output:

Code: Select all

 
 b'$GNGGA,004145.099,,,,,0,0,,,M,,M,,*52\r\n'
b'$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r\n'
b'$GLGSA,A,1,,,,,,,,,,,,,,,*02\r\n'
b'$GNRMC,004145.099,V,,,,,0.00,0.00,270222,,,N*50\r\n'
b'$GNVTG,0.00,T,,M,0.00,N,0.00,K,N*2C\r\n'
from the following code:

Code: Select all

from machine import Pin, UART
import time
uart1= UART(1, baudrate=9600, bits=8, parity=None, stop=1, tx=Pin(4), rx=Pin(5), timeout=300)

while True:
    new_msg = uart1.readline()
    print (new_msg)
   
So I would say it works well! Time to look through the tech docs and start parsing these strings into meaningful information.

Greatly appreciate the help I received on this thread. I am going to edit the OP to reflect what worked.

Post Reply