├── GpsDevice.cpp ├── GpsDevice.h ├── LICENSE ├── README.md ├── UbloxGPSModuleSettingsMessages.txt ├── Ygps.ino └── img ├── ArduinoNanoFront.jpg ├── YaesuGPSSchematic.png ├── YaesuUSBCable.jpg ├── arduino-vx8r-gps-fig01.png ├── ublox-neo6m.jpg ├── vx8r-iso.jpg └── vx8r-lcd.jpg /GpsDevice.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 David Fannin. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE.txt file. 4 | // 5 | #include 6 | #include "GpsDevice.h" 7 | 8 | /* 9 | * GpsDevice 10 | * Class for managing GPS device input and output 11 | * provides NMEA message translation to required Yaesu output. 12 | * version 1.0 13 | * 14 | */ 15 | 16 | GpsDevice::GpsDevice(AltSoftSerial &gdserial) 17 | { 18 | _gdserial = gdserial; 19 | _init(); 20 | } 21 | 22 | char GpsDevice::read(){ 23 | 24 | char c; 25 | 26 | if ( isAvailable() || msg.length() >= GD_MAXLEN ) { 27 | _init(); 28 | } 29 | 30 | if ( _gdserial.available() ) { 31 | c = _gdserial.read(); 32 | switch(c) { 33 | case '$': 34 | sot = true ; 35 | ready = false ; 36 | origmsg = String(c); 37 | msg = String(""); 38 | break; 39 | case '\n': 40 | case '\r': 41 | if(sot) { 42 | sot = false; 43 | ready = true; 44 | filter(); 45 | } else { 46 | _init(); 47 | } 48 | break ; 49 | default: 50 | if( sot ) { 51 | origmsg += c ; 52 | } 53 | break ; 54 | } 55 | } else { 56 | c = NULL ; 57 | } 58 | return c; 59 | } 60 | 61 | bool GpsDevice::isAvailable(){ 62 | return ready; 63 | } 64 | 65 | void GpsDevice::_init(){ 66 | sot = false ; 67 | ready = false ; 68 | msg = String(""); 69 | origmsg = String(""); 70 | } 71 | 72 | void GpsDevice::begin(int speed){ 73 | _gdserial.begin(speed); 74 | } 75 | 76 | 77 | byte GpsDevice::_atoi(char a) { 78 | if( int(a) >= 65 ) 79 | return int(a) - 55; 80 | else 81 | return int(a) - 48; 82 | } 83 | 84 | void GpsDevice::write(char c){ 85 | _gdserial.print(c); 86 | } 87 | bool GpsDevice::valid(){ 88 | 89 | if( ! ready) return false ; 90 | 91 | int plen = origmsg.length() - 3 ; 92 | pchksum=0; 93 | 94 | if ( plen < 1 ) return false ; 95 | 96 | psum[0]= origmsg[plen+1]; 97 | psum[1]= origmsg[plen+2]; 98 | 99 | pchksum = ( _atoi(psum[0]) << 4 ) + _atoi(psum[1]) ; 100 | 101 | String pstr(""); 102 | 103 | for(int i=1;i=0) ; // end do while 200 | // add checksum 201 | msg += "*" + schecksum(msg.substring(1,msg.length())) + "\r" ; 202 | return; 203 | } // end GPGGA 204 | 205 | // GPRMC messages 206 | if( origmsg.startsWith("$GPRMC,")){ 207 | 208 | do { 209 | 210 | pos = parsemsg.indexOf(','); 211 | pi++; 212 | 213 | if(pos != -1) { 214 | switch(pi) { 215 | case 0: 216 | msg = parsemsg.substring(0,pos) + ',' ; 217 | break; 218 | case 7: 219 | msg += _padzero(parsemsg.substring(0,pos),7) + ','; 220 | break; 221 | case 8: 222 | case 9: 223 | msg += _padzero(parsemsg.substring(0,pos),6) + ','; 224 | break; 225 | default: 226 | msg += parsemsg.substring(0,pos) + ',' ; 227 | break; 228 | } 229 | 230 | parsemsg = parsemsg.substring(pos+1,parsemsg.length()); 231 | 232 | } else { 233 | // handles case 14 234 | msg += "," ; 235 | } 236 | 237 | } while(pos >=0) ; // end do while 238 | // add checksum 239 | msg += "*" + schecksum(msg.substring(1,msg.length())) + "\r" ; 240 | return; 241 | } // end GPRMC 242 | // GPTXT messages 243 | if( origmsg.startsWith("$GPTXT,")){ 244 | msg = ""; 245 | return; 246 | } // end GPRMC 247 | 248 | msg = origmsg + "\r" ; 249 | } 250 | -------------------------------------------------------------------------------- /GpsDevice.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 David Fannin. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE.txt file. 4 | // 5 | // Version 1.0 6 | // 7 | #ifndef GpsDevice_h 8 | #define GpsDevice_h 9 | 10 | #include 11 | #include 12 | 13 | // max length of input GPS message 14 | #define GD_MAXLEN 120 15 | 16 | 17 | class GpsDevice 18 | { 19 | public: 20 | GpsDevice(AltSoftSerial &gdserial); 21 | char read(); 22 | bool isAvailable(); 23 | void filter(); 24 | void write(char c); 25 | void begin(int speed); 26 | bool valid(); 27 | byte checksum(String str); 28 | String schecksum(String str); 29 | byte chksum; 30 | byte pchksum; 31 | char psum[2]; 32 | String msg; 33 | String origmsg; 34 | private: 35 | bool sot; 36 | bool ready; 37 | void _init(); 38 | byte _atoi(char a); 39 | String _padzero(String str,int width); 40 | protected: 41 | AltSoftSerial _gdserial; 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, David Fannin 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | arduino-vx8r-gps 2 | ================ 3 | 4 | Arduino code for buidling Yaesu VX-8R Handheld Transmitter-compatible GPS 5 | 6 | # Overview 7 | ![BlockDiagram](https://raw.github.com/dfannin/arduino-vx8r-gps/master/img/vx8r-lcd.jpg) 8 | 9 | The Yaesu VX-8R HT for amateur radio VHF/UHF bands has a built-in APRS (Automatic Position Reporting System) TNC (Terminal Node Controller) to operate as an APRS Beacon transmitter and receiver. To add position and velocity (GPS information) to the transmitted packet, an external Proprietary GPS module must be purchased from Yaesu and connected to HT. 10 | 11 | The goal of this project was to create a compatbile GPS unit, made with open-source and generally available components, that could be used to proivde the position and velocity information for the Yaesu HT. The total cost of the project came in under $43USD, which included having to buy a proprietary cable for $22USB. 12 | 13 | This GPS provides provides all the known GPS features used by the Yaesu, including position, altitude, speed, and direction. It also provides a GPS timestamp, which is used to automatically set the time/date on the HT. The GPS module and Arduino fit in a small candy tin (slightly larger than the Yaesu GPS unit), and can be easily attached to the HT for portible operation. 14 | 15 | The code was designed to work with a specific GPS module (Ublox neo-6m), but should be easily adapted or extended to other NMEA-compatible GPS devices or required features. 16 | 17 | The unit was tested as a automobile beacon transmitter, and provided acurate tracking information as reported by the http://aprs.fi website. 18 | 19 | This project builds from the work done by Taylor Meeks KG7BBG (http://www.lingnik.com/content/reverse-engineering-yaesu-vx-8dr-gps-interface). 20 | 21 | 22 | # Block Diagram 23 | ![BlockDiagram](https://raw.github.com/dfannin/arduino-vx8r-gps/master/img/arduino-vx8r-gps-fig01.png) 24 | 25 | The GPS unit consists of three parts. The GPS module provides NMEA messages via a two wire serial port (tx/rx). These messages are version 2.3 compliant. The messages are sent to the Arduino, using a software serial port (AltSoftSerial), and are parsed, filtered and reformatted for the Yaesu. The reformatted messages are sent to the Yaesu via the hardware serial port using a proprietary Yaesu cable (CT-M11 or equivilent), as the HT uses a 7 pin propreitary connector. 26 | 27 | 28 | # NMEA messages 29 | The following NMEA messages are sent to the Yaesu (thanks to Taylor KG7BBG) : 30 | 31 | * $GPGGA,hhmmss.sss,llll.llll,a,yyyyy.yyyy,a,x,xx,xx.x,xxxxx.x,M,xxxx.x,M,xxx.x,xxxx\*hh 32 | * $GPGLL,llll.llll,a,llll.llll,a,nnnnnn.nnn,a,a\*hh 33 | * $GPGSA,a,n,nn,nn,nn,nn,nn,,,,,,,,n.n,n.n,n.n\*hh 34 | * $GPGSV,n,n,nn,nn,nn,nnn,nn,nn,,,nn,nn,nn,nnn,nn,nn,nn,nnn,\*hh 35 | * $GPRMC,hhmmss.sss,a,llll.llll,a,yyyyy.yyyy,a,xxxx.xx,xxx.xx,xxxxxx,,\*hh 36 | * $GPVTG,,a,,a,n.nn,a,n.n,a,a\*hh 37 | * $GPZDA,hhmmss.sss,xx,xx,xxxx,,\*hh 38 | 39 | Other points: 40 | * Any other message types (like $GPTXT) are filtered from the output stream. 41 | * Fields should be kept as fixed width (and zero padded) 42 | * No modification of the Yaesu -> GPS messages, they are passed through directly. This didn't appear to cause any issues. 43 | 44 | 45 | # Hardware 46 | 47 | ## Schematic 48 | ![BlockDiagram](https://raw.github.com/dfannin/arduino-vx8r-gps/master/img/YaesuGPSSchematic.png) 49 | 50 | ## NMEA-compatible GPS Module 51 | A Ublox Neo-6m GPS module (NEO-6M-0-001) was used (around $15USD on Ebay), including an active antenna. It is a stand-alone GPS module. According to the datasheet, the GPS chip uses about 36mA during operation. The Ublox has four connections, TX, RX, VCC and GND. The module has a voltage regulator, and can take up to 6+ volts input. The serial port is set to 9600,N,1 as a default. 52 | 53 | I had to change the ublox firmware settings to produced the desired output using the Ublox Ucenter software (available from the Ublox website). You'll need to connect the tx/rx and gnd pins to a USB/TTL 5/3.3v FTDI or equivlent cable and connect to a computer running the Ucenter (windows based) software. I used Ubuntu/Wine to run the Ucenter software - it would crash sometimes, but I was to able to reprogram the module. I changed the following settings and saved them to the EEPROM: Output: NMEA, Output Version 2.3, Compatiblity Mode (checked), GPZDA messages set output to true. 54 | 55 | The Ublox is cross-over connected to an Arduino software serial port using AltSoftSerial, which uses pins D8 and D9 (RX and TX), so connect the Ublox RX to the Arduino TX pin and vis versa. The Ublox was connected to the power supply, which was 4 x AAA batteries (6v+). 56 | ![Ublox](https://raw.github.com/dfannin/arduino-vx8r-gps/master/img/ublox-neo6m.jpg) 57 | 58 | 59 | ## Arduino 60 | An Arduino Nano v3 (atmel328, 5v, 16Mhz, 32k ram) was used, as its small size (0.73" x 1.70"), low power consumption (40mA), soldered connections and performance was a good fit for this application. The Nano was powered by the same 6 volt power supply as the GPS module. 61 | 62 | The Nano is connected to the TX/RX pins of the GPS module, and is also connected to the serial port of the Yaesu HT. Nano Pins D0/D1 (the hardware TX/RX pins) were used for Yaesu serial port. Since the Yaesu is expecting TTL 3.3v levels for the serial port, a resistor voltage divider was used to bring the Nano 5v TTL level down to 3.3v. A better approach would be to use a logic level shift chip, but the simple bridge appears to work well, and it was very easy to construct , by bridging the two resistors (270 and 470 ohms, 1/4 watt) across the Nano board. The bridge is only used on the Arduino TX side, as the RX is driven at the 3.3v by the Yaesu, and doesn't require the voltage drop. 63 | 64 | The Nano can still be updated using the Usb interface; However, since the USB tx/rx pins are shared with D0/D1, you won't be able to connect to the Yaesu and the USB interface at the same time. You should disconnect the Yaesu cable from the unit whenever doing a new software upgrade to the Nano. As a benefit, You can see the GPS output stream from the Nano when you connect to the USB port and use a term emulator, which makes it easier to debug. I did this to avoid having two software serial ports. 65 | 66 | ![Ublox](https://raw.github.com/dfannin/arduino-vx8r-gps/master/img/ArduinoNanoFront.jpg) 67 | 68 | ### Arduino Software 69 | The software provides the serial port forwarding and NMEA message translation between HT and GPS module. A new class was created _GpsDevice_ that does the serial port stream reading, parsing, filtering and output. See the Extension/Modificaiton section for hints on how to modify this class if you require other types of filtering or translation. The checksums from the GPS module are calculated and compared before passing thru messages, and new checksums are generated for modified messages. Other have observed, and I have seen that the Yaesu HT does not valid the checksums, it doesn't to add much overhead. 70 | 71 | The serial port reads are done character by character, alternating each serial port stream; This was done to cut down on possible delay time between buffer reads and reducing the risk of buffer overruns. So far, no issues with overruns or lost messages have been observed. 72 | 73 | The Arduino library _AltSoftSerial_ is required to be installed in your Arduino Development environment. No other external libraries are required. 74 | 75 | ## Yaesu HT Cable 76 | 77 | The Yaesu VX-8R uses a proprietary 7 pin connector, which I have been unable to find. Therefore, I purchased a rather expensive USB cable (normally used for programing the Yaesu) and cut the USB end off, and wired the 3 pins (TX,RX and GND) into the Nano as shown. A better option would be to use the CT-M11 cable from Yaesu, which provides all the pins outs, including the 3.3V power supply. if you get a 3.3v Nano, you should be able to power the GPS and Nano from the HT power supply directly, rather than use an external battery pack. 78 | 79 | ![Ublox](https://raw.github.com/dfannin/arduino-vx8r-gps/master/img/YaesuUSBCable.jpg) 80 | 81 | ## Case and Mounting 82 | 83 | I used a small mint tin (about half the size of an arduino tin) for the GPS and Nano. I installed the GPS antenna on the outside of the case, and drilled holes for the antenna cable, Yaesu HT cable and an opening for the Nano usb connector. After wiring the circuit and boards together, I used hot glue to mount all the components in the case. I used a thin wall pvc pipe to create a removable mount for the GPS and battery, which can attach/detach using the belt clip. 84 | 85 | It's important to use a common ground for all modules and power supply, to minimize RF interference, including the gps/Nano, case and Yaesu cable. 86 | 87 | ![BlockDiagram](https://raw.github.com/dfannin/arduino-vx8r-gps/master/img/vx8r-iso.jpg) 88 | 89 | # Use 90 | 91 | # Extending/Modifying Output 92 | 93 | 94 | -------------------------------------------------------------------------------- /UbloxGPSModuleSettingsMessages.txt: -------------------------------------------------------------------------------- 1 | Ublox NEO-6M GPS Module (UBX-G60xx) 2 | firmware version: 7.03 3 | firmware settings: 4 | speed 9600,8,N,1 5 | NMEA version 2.3 6 | compatibility mode set 7 | GPZDA message set active 8 | 9 | --------- Messages -------------------------------------------------------- 10 | 11 | // GGA Message 12 | // Ublox format 13 | U $GPGGA,175908.000,3742.4413,N,12157.6537,W,1,05,2.2,226.5,M,-29.4,M,,0000*6F 14 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Yaesu format 16 | Y $GPGGA,123223.000,4131.2334,N,00021.1216,E,1,04,02.7,00123.4,M,0051.7,M,000.0,0000*41 17 | Y $GPGGA,hhmmss.sss,llll.llll,a,yyyyy.yyyy,a,x,xx,xx.x,xxxxx.x,M,xxxx.x,M,xxx.x,xxxx*hh 18 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 19 | * * * * 20 | 21 | // GLL - no change 22 | U $GPGLL,3742.4413,N,12157.6537,W,175908.000,A,A*4E 23 | no change 24 | 25 | // GSA - no change 26 | U $GPGSA,A,3,32,31,01,23,11,,,,,,,,4.7,2.2,4.1*37 27 | 28 | // GSV - no change 29 | U $GPGSV,3,1,11,01,47,238,38,06,,,21,11,24,217,33,13,07,260,*4D 30 | 31 | // RMC 32 | // Ublox format 33 | U $GPRMC,175909.000,A,3742.4410,N,12157.6535,W,0.59,,080414,,,A*62 34 | * ** 35 | // Yaesu format 36 | Y $GPRMC,123223.000,A,4131.2334,N,00021.1216,E,0000.00,291.33,301011,,*3E 37 | Y $GPRMC,hhmmss.sss,A,llll.llll,a,yyyyy.yyyy,a,xxxx.xx,xxx.xx,xxxxxx,,*hh 38 | 0 1 2 3 4 5 6 7 8 9 10 39 | * * 40 | 41 | // VTG - no change 42 | U $GPVTG,,T,,M,0.46,N,0.8,K,A*19 43 | 44 | // ZDA - no change 45 | // Ublox format 46 | U $GPZDA,175908.000,08,04,2014,,*5F 47 | // Yaesu format 48 | Y $GPZDA,123223.000,30,10,2011,,*55 49 | Y $GPZDA,hhmmss.sss,xx,xx,xxxx,,*hh 50 | 51 | // TXT - remove message 52 | U $GPTXT,01,01,02,u-blox ag - www.u-blox.com*50 53 | 54 | -------------------------------------------------------------------------------- /Ygps.ino: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 David Fannin. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE.txt file. 4 | // 5 | // Version 1.0 6 | #include 7 | #include "GpsDevice.h" 8 | 9 | AltSoftSerial gpsserial; 10 | 11 | GpsDevice gps(gpsserial); 12 | 13 | void setup() { 14 | Serial.begin(9600); 15 | gps.begin(9600); 16 | } 17 | 18 | void loop(){ 19 | 20 | char c ; 21 | 22 | gps.read(); // read a character from gps 23 | 24 | // if parsed, filtered message is available, send it to the Yaesu 25 | if(gps.isAvailable()) { 26 | // make sure the checksum is valid 27 | if (gps.valid() ) { 28 | Serial.println(gps.msg); 29 | } 30 | } 31 | 32 | // send yaesu output to the gps 33 | if(Serial.available()) { 34 | c = Serial.read(); 35 | gps.write(c); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /img/ArduinoNanoFront.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfannin/arduino-vx8r-gps/40c8d6411c22fc60a7baa857e3aab7ac7ed2b95a/img/ArduinoNanoFront.jpg -------------------------------------------------------------------------------- /img/YaesuGPSSchematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfannin/arduino-vx8r-gps/40c8d6411c22fc60a7baa857e3aab7ac7ed2b95a/img/YaesuGPSSchematic.png -------------------------------------------------------------------------------- /img/YaesuUSBCable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfannin/arduino-vx8r-gps/40c8d6411c22fc60a7baa857e3aab7ac7ed2b95a/img/YaesuUSBCable.jpg -------------------------------------------------------------------------------- /img/arduino-vx8r-gps-fig01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfannin/arduino-vx8r-gps/40c8d6411c22fc60a7baa857e3aab7ac7ed2b95a/img/arduino-vx8r-gps-fig01.png -------------------------------------------------------------------------------- /img/ublox-neo6m.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfannin/arduino-vx8r-gps/40c8d6411c22fc60a7baa857e3aab7ac7ed2b95a/img/ublox-neo6m.jpg -------------------------------------------------------------------------------- /img/vx8r-iso.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfannin/arduino-vx8r-gps/40c8d6411c22fc60a7baa857e3aab7ac7ed2b95a/img/vx8r-iso.jpg -------------------------------------------------------------------------------- /img/vx8r-lcd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfannin/arduino-vx8r-gps/40c8d6411c22fc60a7baa857e3aab7ac7ed2b95a/img/vx8r-lcd.jpg --------------------------------------------------------------------------------