Here is another quick demonstration of USB Host Shield 2.0 Library. This article describes how to communicate to Navibee GM720 GPS receiver based on SiRF Star III chipset and PL2303 USB to serial converter. This GPS device is available on eBay for around $25 new, used units can sometimes be found for $10 or even less. The receiver has waterproof case, magnet mount and comes with 6 foot cable. Another nice feature of this device is its 40mA current consumption. Here are some pictures of the unit – PCB, internal antenna, as well as front and back of the original packaging.
“Classic” GPS receiver sends and receives NMEA 0183 messages via serial port at 4800 bps. Modern GPS units often support faster speeds and vendor-specific messages. However, they mimic classic GPS unit behavior – at power-on they start sending basic navigation messages at 4800 bps. The following sketch outputs messages, received from Navibee GM720 GPS unit via its built-in PL2303 USB to serial converter connected to USB Host Shield. Full text of the sketch is available on gitHub, below is just a fragment where speed is set to 4800.
The OnInit()
member function is called to change serial parameters after initialization. A lc
structure of type LINE_CODING
is declared on line 14. It is filled with baud rate (line 15) and number of data bits per byte (line 18) and then sent to Pl
instance in line 20.
Compile the sketch, load and run. The output is depicted on a screenshot after the code fragment.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | uint8_t PLAsyncOper::OnInit(ACM *pacm) { uint8_t rcode; // Set DTR = 1 rcode = pacm->SetControlLineState(1); if (rcode) { ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode); return rcode; } LINE_CODING lc; lc.dwDTERate = 4800; //default serial speed of GPS unit lc.bCharFormat = 0; lc.bParityType = 0; lc.bDataBits = 8; rcode = pacm->SetLineCoding(&lc); if (rcode) ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode); return rcode; } |
Next I want to show how to send raw GPS output to a NMEA 0183 message parser. For the following code example I used Mikal Hart’s TinyGps library. Since the library itself is not handling serial input, it was only necessary to make changes in the application sketch. pl2303_tinygps
sketch is almost exact copy of Mikal’s test_with_gps_device
library example. I added PL2303 initialization, removed NewSoftSerial
code and modified feedgps()
function. The modified code listing is below, followed by terminal screenshot – as can be seen, parsed output makes much more sense.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | bool feedgps() { uint8_t rcode; uint8_t buf[64]; //serial buffer equals Max.packet size of bulk-IN endpoint uint16_t rcvd = 64; { /* reading the GPS */ rcode = Pl.RcvData(&rcvd, buf); if (rcode && rcode != hrNAK) ErrorMessage<uint8_t>(PSTR("Ret"), rcode); rcode = false; if( rcvd ) { //more than zero bytes received for( uint16_t i=0; i < rcvd; i++ ) { if( gps.encode(buf[i])) { //feed a character to gps object rcode = true; }//if( gps.encode(buf[i]... }//for( uint16_t i=0; i < rcvd; i++... }//if( rcvd... } return( rcode ); } |
As have been just demonstrated, new USB Host Shield Library greatly simplifies USB code development and allows for easy mixing of code from different sources. The code presented in this article is not specific to any particular GPS receiver either and can be used with any device which uses one of USB to serial converters supported by library. Also, it can be used for interfacing with serial GPS devices using generic PL2303 converter, described in the previous article, with no modification.
Oleg.
This is great!!!
I plugged my Holux SiRF starIII (model GR-213) into the Arduino w/ USB Shield and it worked first time with no modification to the code. This is GREAT!
Thanks,
Steve
While I’m waiting for your new Shield…
I tried it with the old library and old Host shield.
board_test:
all pass until USB Connectivity test waiting for device
I have Qstarz BT-q1000xt GPS
PC driver:
usbser.sys
pl2303_tinygps:
PL Init
Ret: 0D
Want to see hub_demo output?
It uses the same PC driver as UNO
Should work then.
Works with Windows terminal.
pl2303_tinygps:
PL Init
Ret: 0D…
hub_demo:
01 GPS
—
Device descriptor:
Descriptor Length: 12
Descriptor type: 01
USB version: 0200
Device class: 02
Device Subclass: 00
Device Protocol: 00
Max.packet size: 40
Vendor ID: 0E8D
Product ID: 3329
Revision ID: 0100
Mfg.string index: 03
Prod.string index: 04
Serial number index: 00
Number of conf.: 01
Configuration descriptor:
Total length: 0043
Num.intf: 02
Conf.value: 01
Conf.string: 00
Attr.: 80
Max.pwr: FA
Interface descriptor:
Intf.number: 00
Alt.: 00
Endpoints: 02
Intf. Class: 0A
Intf. Subclass: 00
Intf. Protocol: 00
Intf.string: 01
Endpoint descriptor:
Endpoint address: 81
Attr.: 02
Max.pkt size: 0040
Polling interval: 00
Endpoint descriptor:
Endpoint address: 01
Attr.: 02
Max.pkt size: 0040
Polling interval: 00
Interface descriptor:
Intf.number: 01
Alt.: 00
Endpoints: 01
Intf. Class: 02
Intf. Subclass: 02
Intf. Protocol: 01
Intf.string: 02
Endpoint descriptor:
Endpoint address: 82
Attr.: 03
Max.pkt size: 0040
Polling interval: 01
Addr:1(0.0.1)
Got your Host! First I noticed I cannot upload a Sketch while it’s attached. That seems wrong. Then I tried pl2303_gps. OSCOKIRQ failed to assert. How do I test it?
Have you soldered all the headers, including 2×3 one? If you can, take a good picture of the shield and send it to me so I can check. Also, check visually for shorts – USB Host Shield doesn’t use serial lines, through which sketches are uploaded so it can be shorted pin somewhere.
Ah thank you! I didn’t realize the 2×3 header was important silly me. I left it out. Would this explain my symptoms?
It would explain “OSCOKIRQ..” error. As far as inability to load sketches with shield attached, check your soldering for shorts.
No shorts that I can see. Which pins should I measure? Still cannot load sketches until I remove the shield. Your Sketches return 0D.
Razr v3m
acm_terminal
Start
ACM Init
getDevDescr:D
GPS
pl2303_gps
PL Init
Ret: 0D
acm_terminal
Addr:1
NC:1
Conf.Val: 01
Iface Num: 01
Alt.Set: 00
Endpoint descriptor:
Length: 07
Type: 05
Address: 82
Attributes: 03
MaxPktSize: 0040
Poll Intrv: 01
Conf.Val: 01
Iface Num: 00
Alt.Set: 00
Endpoint descriptor:
Length: 07
Type: 05
Address: 81
Attributes: 02
MaxPktSize: 0040
Poll Intrv: 00
Conf.Val: 01
Iface Num: 00
Alt.Set: 00
Endpoint descriptor:
Length: 07
Type: 05
Address: 01
Attributes: 02
MaxPktSize: 0040
Poll Intrv: 00
Conf:1
SetControlLineState: 05
OnInit:5
Which Arduino board are you using? The output looks good – shield works fine and communicates to USB device. Have you had any luck with pl2303 device?
New Uno. Both of the sketches above return D for both devices I have. As I mentioned before the GPS uses the same driver as Uno on my PC. One thing at a time. Why can’t I load sketches? All the other shield allow me to. Should I measure the resistance on the serial lines with and without? I doesn’t seem like a power issue because it runs sketches.
avrdude: stk500_getsync(): not in sync: resp=0x2b
avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x41
Alright 2 things:
Are you certain the Razr v3m is the same as the Razr as far as drivers?
They could be slightly different. Run hub_demo with your phone attached (you don’t need a hub) and send me the output – I will compare it to mine.
Apparently, there is something foreign on serial lines. USB Host Shield doesn’t use them so there should be no difference whether it is attached or not.
Sorry for the delay. Bent the serial pins now I can load Sketches. Same problem as before otherwise. Ret: 0D with both devices. Will email details.
Hello,
I ma not in the correct ‘forum’ but there seems to be a vast knowledge of the MAX3421 in this project, so I asking for help here.
My project is a intervalometer for my Nikon D40 DSLR camera. I want to make timelapse videos by sending the shutter release commands to the camera at over a period of time.
Only one device will be connected to D+ and D-, so I am assumming that the MAX3421 will assign the endpoint as EP1???
Below is how I understand the MAX3421 to work. Please check my program flow and let me know if I am missing any steps.
Set Mode:
1. Assert SS low.
2. Clock out SPI command byte 11011010 – selects R27 (MODE) for a write.
3. Clock out 11000001 – sets D+ and D- pulldowns and Host mode.
3. Assert SS high to end.
Read HRSL status register:
4. Assert SS low.
5. Clock out SPI command byte 11111000 – selects R31 (HRSL) for a read.
6. Clock in R31 data and check for JSTATUS AND KSTATUS to determine when a device has been connected or disconnected and is a Low or High speed device.
7. Loop step 6 until detected.
8. Assert SS high to end.
Load Send FIFO register with camera shutter release command data bytes:
9. Assert SS low.
10. Clock out SPI command byte 00010010 – selects R2 (SNDFIFO) for a write.
11. Clock out data bytes to load Send FIFO.
12. Assert SS high to end.
Load Send Byte Count register with the number of data bytes in Send FIFO:
13. Assert SS low.
14. Clock out SPI command byte 00111010 – selects R7 (SNDBC) for a write.
15. Clock out number of bytes loaded into SNDFIFO.
16. Assert SS high to end.
Send data to device by writting to HXFR register:
17. Assert SS low.
18. Clock out SPI command byte 11110010 – selects R30 (HXFR) for a write.
19. Clock out 00100001 – selects Bulk Transfer and EP1.
20. Assert SS high to end.
21. Pause x seconds then repeat the write to HXFR register.
Thank you.
John
It is not that easy. Before sending camera control commands you need to enumerate the peripheral and open PTP session. Please take a look at the code posted on github.
Ok, my code abilities are limited to Basic, so anything in C is pretty much foreign.
But I will take a look anyway, maybe I can extrapolate some good info.
Thanks,
John
I don’t need to know about anyother USB device that could possibly be connected to my project.
The Nikon D40 is the only device. Therefore, if I
OK, I used a USB analyzer and found the Nikon D40 uses Endpoint 2 to receive BULK_OR_INTERRUPT_TRANSFER data.
Using DIY PhotoBits and the analyzer I now know the Nikon ‘CaptureImage’ command bytes.
Knowing that much, will my program flow above work?
Thanks,
John
Hello, I have installed the usb shield with a usb gps. and the serial monitor after the ‘start I will show (Ret: FF). I would like to know if I need to do anything special.
thanks
The GPS should start outputting data right away.
Hello there, i would just like to ask if this gps device will be able to send data to an android application. I would like to build an android app that will be able to receive a signal from a remote gps beacon. my plan is, upon a trigger on a circuit connected to the beacon, it should send the location to an android phone and the android app displays the location on the phone. do i make sense here? Your answer will be greatly appreciated as im working this for my thesis. Thanks and Godbless!
Android phones typically have a built-in GPS receiver, just read it to get coordinates.
I have actually been working on something quite similar. I simply have a Arduino connected to a SIM300 GSM module and a GPS module.
It then sends it’s coordinates via SMS to the Android phone which then shows it on a map.
You can find the source for the Android app here: https://github.com/Lauszus/WeatherBalloonApp and the Arduino code here: https://github.com/Lauszus/WeatherBalloon. Also check out the library I wrote for the SIM300 GSM module: https://github.com/Lauszus/GSMSIM300 🙂