├── LICENSE
├── README.md
├── examples
├── BasicExample
│ └── BasicExample.ino
├── DeviceExample
│ └── DeviceExample.ino
├── FullExample
│ └── FullExample.ino
├── KitchenSink
│ └── KitchenSink.ino
├── SatElevTracker
│ ├── SatElevTracker.ino
│ └── sample_satellite_elevation_log.txt
├── SatelliteTracker
│ └── SatelliteTracker.ino
└── UsingCustomFields
│ └── UsingCustomFields.ino
├── library.json
├── library.properties
└── src
├── TinyGPSPlus.cpp
└── TinyGPSPlus.h
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | GNU GENERAL PUBLIC LICENSE
3 | Version 3, 29 June 2007
4 |
5 | Copyright (C) 2007 Free Software Foundation, Inc.
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The GNU General Public License is a free, copyleft license for
12 | software and other kinds of works.
13 |
14 | The licenses for most software and other practical works are designed
15 | to take away your freedom to share and change the works. By contrast,
16 | the GNU General Public License is intended to guarantee your freedom to
17 | share and change all versions of a program--to make sure it remains free
18 | software for all its users. We, the Free Software Foundation, use the
19 | GNU General Public License for most of our software; it applies also to
20 | any other work released this way by its authors. You can apply it to
21 | your programs, too.
22 |
23 | When we speak of free software, we are referring to freedom, not
24 | price. Our General Public Licenses are designed to make sure that you
25 | have the freedom to distribute copies of free software (and charge for
26 | them if you wish), that you receive source code or can get it if you
27 | want it, that you can change the software or use pieces of it in new
28 | free programs, and that you know you can do these things.
29 |
30 | To protect your rights, we need to prevent others from denying you
31 | these rights or asking you to surrender the rights. Therefore, you have
32 | certain responsibilities if you distribute copies of the software, or if
33 | you modify it: responsibilities to respect the freedom of others.
34 |
35 | For example, if you distribute copies of such a program, whether
36 | gratis or for a fee, you must pass on to the recipients the same
37 | freedoms that you received. You must make sure that they, too, receive
38 | or can get the source code. And you must show them these terms so they
39 | know their rights.
40 |
41 | Developers that use the GNU GPL protect your rights with two steps:
42 | (1) assert copyright on the software, and (2) offer you this License
43 | giving you legal permission to copy, distribute and/or modify it.
44 |
45 | For the developers' and authors' protection, the GPL clearly explains
46 | that there is no warranty for this free software. For both users' and
47 | authors' sake, the GPL requires that modified versions be marked as
48 | changed, so that their problems will not be attributed erroneously to
49 | authors of previous versions.
50 |
51 | Some devices are designed to deny users access to install or run
52 | modified versions of the software inside them, although the manufacturer
53 | can do so. This is fundamentally incompatible with the aim of
54 | protecting users' freedom to change the software. The systematic
55 | pattern of such abuse occurs in the area of products for individuals to
56 | use, which is precisely where it is most unacceptable. Therefore, we
57 | have designed this version of the GPL to prohibit the practice for those
58 | products. If such problems arise substantially in other domains, we
59 | stand ready to extend this provision to those domains in future versions
60 | of the GPL, as needed to protect the freedom of users.
61 |
62 | Finally, every program is threatened constantly by software patents.
63 | States should not allow patents to restrict development and use of
64 | software on general-purpose computers, but in those that do, we wish to
65 | avoid the special danger that patents applied to a free program could
66 | make it effectively proprietary. To prevent this, the GPL assures that
67 | patents cannot be used to render the program non-free.
68 |
69 | The precise terms and conditions for copying, distribution and
70 | modification follow.
71 |
72 | TERMS AND CONDITIONS
73 |
74 | 0. Definitions.
75 |
76 | "This License" refers to version 3 of the GNU General Public License.
77 |
78 | "Copyright" also means copyright-like laws that apply to other kinds of
79 | works, such as semiconductor masks.
80 |
81 | "The Program" refers to any copyrightable work licensed under this
82 | License. Each licensee is addressed as "you". "Licensees" and
83 | "recipients" may be individuals or organizations.
84 |
85 | To "modify" a work means to copy from or adapt all or part of the work
86 | in a fashion requiring copyright permission, other than the making of an
87 | exact copy. The resulting work is called a "modified version" of the
88 | earlier work or a work "based on" the earlier work.
89 |
90 | A "covered work" means either the unmodified Program or a work based
91 | on the Program.
92 |
93 | To "propagate" a work means to do anything with it that, without
94 | permission, would make you directly or secondarily liable for
95 | infringement under applicable copyright law, except executing it on a
96 | computer or modifying a private copy. Propagation includes copying,
97 | distribution (with or without modification), making available to the
98 | public, and in some countries other activities as well.
99 |
100 | To "convey" a work means any kind of propagation that enables other
101 | parties to make or receive copies. Mere interaction with a user through
102 | a computer network, with no transfer of a copy, is not conveying.
103 |
104 | An interactive user interface displays "Appropriate Legal Notices"
105 | to the extent that it includes a convenient and prominently visible
106 | feature that (1) displays an appropriate copyright notice, and (2)
107 | tells the user that there is no warranty for the work (except to the
108 | extent that warranties are provided), that licensees may convey the
109 | work under this License, and how to view a copy of this License. If
110 | the interface presents a list of user commands or options, such as a
111 | menu, a prominent item in the list meets this criterion.
112 |
113 | 1. Source Code.
114 |
115 | The "source code" for a work means the preferred form of the work
116 | for making modifications to it. "Object code" means any non-source
117 | form of a work.
118 |
119 | A "Standard Interface" means an interface that either is an official
120 | standard defined by a recognized standards body, or, in the case of
121 | interfaces specified for a particular programming language, one that
122 | is widely used among developers working in that language.
123 |
124 | The "System Libraries" of an executable work include anything, other
125 | than the work as a whole, that (a) is included in the normal form of
126 | packaging a Major Component, but which is not part of that Major
127 | Component, and (b) serves only to enable use of the work with that
128 | Major Component, or to implement a Standard Interface for which an
129 | implementation is available to the public in source code form. A
130 | "Major Component", in this context, means a major essential component
131 | (kernel, window system, and so on) of the specific operating system
132 | (if any) on which the executable work runs, or a compiler used to
133 | produce the work, or an object code interpreter used to run it.
134 |
135 | The "Corresponding Source" for a work in object code form means all
136 | the source code needed to generate, install, and (for an executable
137 | work) run the object code and to modify the work, including scripts to
138 | control those activities. However, it does not include the work's
139 | System Libraries, or general-purpose tools or generally available free
140 | programs which are used unmodified in performing those activities but
141 | which are not part of the work. For example, Corresponding Source
142 | includes interface definition files associated with source files for
143 | the work, and the source code for shared libraries and dynamically
144 | linked subprograms that the work is specifically designed to require,
145 | such as by intimate data communication or control flow between those
146 | subprograms and other parts of the work.
147 |
148 | The Corresponding Source need not include anything that users
149 | can regenerate automatically from other parts of the Corresponding
150 | Source.
151 |
152 | The Corresponding Source for a work in source code form is that
153 | same work.
154 |
155 | 2. Basic Permissions.
156 |
157 | All rights granted under this License are granted for the term of
158 | copyright on the Program, and are irrevocable provided the stated
159 | conditions are met. This License explicitly affirms your unlimited
160 | permission to run the unmodified Program. The output from running a
161 | covered work is covered by this License only if the output, given its
162 | content, constitutes a covered work. This License acknowledges your
163 | rights of fair use or other equivalent, as provided by copyright law.
164 |
165 | You may make, run and propagate covered works that you do not
166 | convey, without conditions so long as your license otherwise remains
167 | in force. You may convey covered works to others for the sole purpose
168 | of having them make modifications exclusively for you, or provide you
169 | with facilities for running those works, provided that you comply with
170 | the terms of this License in conveying all material for which you do
171 | not control copyright. Those thus making or running the covered works
172 | for you must do so exclusively on your behalf, under your direction
173 | and control, on terms that prohibit them from making any copies of
174 | your copyrighted material outside their relationship with you.
175 |
176 | Conveying under any other circumstances is permitted solely under
177 | the conditions stated below. Sublicensing is not allowed; section 10
178 | makes it unnecessary.
179 |
180 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
181 |
182 | No covered work shall be deemed part of an effective technological
183 | measure under any applicable law fulfilling obligations under article
184 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
185 | similar laws prohibiting or restricting circumvention of such
186 | measures.
187 |
188 | When you convey a covered work, you waive any legal power to forbid
189 | circumvention of technological measures to the extent such circumvention
190 | is effected by exercising rights under this License with respect to
191 | the covered work, and you disclaim any intention to limit operation or
192 | modification of the work as a means of enforcing, against the work's
193 | users, your or third parties' legal rights to forbid circumvention of
194 | technological measures.
195 |
196 | 4. Conveying Verbatim Copies.
197 |
198 | You may convey verbatim copies of the Program's source code as you
199 | receive it, in any medium, provided that you conspicuously and
200 | appropriately publish on each copy an appropriate copyright notice;
201 | keep intact all notices stating that this License and any
202 | non-permissive terms added in accord with section 7 apply to the code;
203 | keep intact all notices of the absence of any warranty; and give all
204 | recipients a copy of this License along with the Program.
205 |
206 | You may charge any price or no price for each copy that you convey,
207 | and you may offer support or warranty protection for a fee.
208 |
209 | 5. Conveying Modified Source Versions.
210 |
211 | You may convey a work based on the Program, or the modifications to
212 | produce it from the Program, in the form of source code under the
213 | terms of section 4, provided that you also meet all of these conditions:
214 |
215 | a) The work must carry prominent notices stating that you modified
216 | it, and giving a relevant date.
217 |
218 | b) The work must carry prominent notices stating that it is
219 | released under this License and any conditions added under section
220 | 7. This requirement modifies the requirement in section 4 to
221 | "keep intact all notices".
222 |
223 | c) You must license the entire work, as a whole, under this
224 | License to anyone who comes into possession of a copy. This
225 | License will therefore apply, along with any applicable section 7
226 | additional terms, to the whole of the work, and all its parts,
227 | regardless of how they are packaged. This License gives no
228 | permission to license the work in any other way, but it does not
229 | invalidate such permission if you have separately received it.
230 |
231 | d) If the work has interactive user interfaces, each must display
232 | Appropriate Legal Notices; however, if the Program has interactive
233 | interfaces that do not display Appropriate Legal Notices, your
234 | work need not make them do so.
235 |
236 | A compilation of a covered work with other separate and independent
237 | works, which are not by their nature extensions of the covered work,
238 | and which are not combined with it such as to form a larger program,
239 | in or on a volume of a storage or distribution medium, is called an
240 | "aggregate" if the compilation and its resulting copyright are not
241 | used to limit the access or legal rights of the compilation's users
242 | beyond what the individual works permit. Inclusion of a covered work
243 | in an aggregate does not cause this License to apply to the other
244 | parts of the aggregate.
245 |
246 | 6. Conveying Non-Source Forms.
247 |
248 | You may convey a covered work in object code form under the terms
249 | of sections 4 and 5, provided that you also convey the
250 | machine-readable Corresponding Source under the terms of this License,
251 | in one of these ways:
252 |
253 | a) Convey the object code in, or embodied in, a physical product
254 | (including a physical distribution medium), accompanied by the
255 | Corresponding Source fixed on a durable physical medium
256 | customarily used for software interchange.
257 |
258 | b) Convey the object code in, or embodied in, a physical product
259 | (including a physical distribution medium), accompanied by a
260 | written offer, valid for at least three years and valid for as
261 | long as you offer spare parts or customer support for that product
262 | model, to give anyone who possesses the object code either (1) a
263 | copy of the Corresponding Source for all the software in the
264 | product that is covered by this License, on a durable physical
265 | medium customarily used for software interchange, for a price no
266 | more than your reasonable cost of physically performing this
267 | conveying of source, or (2) access to copy the
268 | Corresponding Source from a network server at no charge.
269 |
270 | c) Convey individual copies of the object code with a copy of the
271 | written offer to provide the Corresponding Source. This
272 | alternative is allowed only occasionally and noncommercially, and
273 | only if you received the object code with such an offer, in accord
274 | with subsection 6b.
275 |
276 | d) Convey the object code by offering access from a designated
277 | place (gratis or for a charge), and offer equivalent access to the
278 | Corresponding Source in the same way through the same place at no
279 | further charge. You need not require recipients to copy the
280 | Corresponding Source along with the object code. If the place to
281 | copy the object code is a network server, the Corresponding Source
282 | may be on a different server (operated by you or a third party)
283 | that supports equivalent copying facilities, provided you maintain
284 | clear directions next to the object code saying where to find the
285 | Corresponding Source. Regardless of what server hosts the
286 | Corresponding Source, you remain obligated to ensure that it is
287 | available for as long as needed to satisfy these requirements.
288 |
289 | e) Convey the object code using peer-to-peer transmission, provided
290 | you inform other peers where the object code and Corresponding
291 | Source of the work are being offered to the general public at no
292 | charge under subsection 6d.
293 |
294 | A separable portion of the object code, whose source code is excluded
295 | from the Corresponding Source as a System Library, need not be
296 | included in conveying the object code work.
297 |
298 | A "User Product" is either (1) a "consumer product", which means any
299 | tangible personal property which is normally used for personal, family,
300 | or household purposes, or (2) anything designed or sold for incorporation
301 | into a dwelling. In determining whether a product is a consumer product,
302 | doubtful cases shall be resolved in favor of coverage. For a particular
303 | product received by a particular user, "normally used" refers to a
304 | typical or common use of that class of product, regardless of the status
305 | of the particular user or of the way in which the particular user
306 | actually uses, or expects or is expected to use, the product. A product
307 | is a consumer product regardless of whether the product has substantial
308 | commercial, industrial or non-consumer uses, unless such uses represent
309 | the only significant mode of use of the product.
310 |
311 | "Installation Information" for a User Product means any methods,
312 | procedures, authorization keys, or other information required to install
313 | and execute modified versions of a covered work in that User Product from
314 | a modified version of its Corresponding Source. The information must
315 | suffice to ensure that the continued functioning of the modified object
316 | code is in no case prevented or interfered with solely because
317 | modification has been made.
318 |
319 | If you convey an object code work under this section in, or with, or
320 | specifically for use in, a User Product, and the conveying occurs as
321 | part of a transaction in which the right of possession and use of the
322 | User Product is transferred to the recipient in perpetuity or for a
323 | fixed term (regardless of how the transaction is characterized), the
324 | Corresponding Source conveyed under this section must be accompanied
325 | by the Installation Information. But this requirement does not apply
326 | if neither you nor any third party retains the ability to install
327 | modified object code on the User Product (for example, the work has
328 | been installed in ROM).
329 |
330 | The requirement to provide Installation Information does not include a
331 | requirement to continue to provide support service, warranty, or updates
332 | for a work that has been modified or installed by the recipient, or for
333 | the User Product in which it has been modified or installed. Access to a
334 | network may be denied when the modification itself materially and
335 | adversely affects the operation of the network or violates the rules and
336 | protocols for communication across the network.
337 |
338 | Corresponding Source conveyed, and Installation Information provided,
339 | in accord with this section must be in a format that is publicly
340 | documented (and with an implementation available to the public in
341 | source code form), and must require no special password or key for
342 | unpacking, reading or copying.
343 |
344 | 7. Additional Terms.
345 |
346 | "Additional permissions" are terms that supplement the terms of this
347 | License by making exceptions from one or more of its conditions.
348 | Additional permissions that are applicable to the entire Program shall
349 | be treated as though they were included in this License, to the extent
350 | that they are valid under applicable law. If additional permissions
351 | apply only to part of the Program, that part may be used separately
352 | under those permissions, but the entire Program remains governed by
353 | this License without regard to the additional permissions.
354 |
355 | When you convey a copy of a covered work, you may at your option
356 | remove any additional permissions from that copy, or from any part of
357 | it. (Additional permissions may be written to require their own
358 | removal in certain cases when you modify the work.) You may place
359 | additional permissions on material, added by you to a covered work,
360 | for which you have or can give appropriate copyright permission.
361 |
362 | Notwithstanding any other provision of this License, for material you
363 | add to a covered work, you may (if authorized by the copyright holders of
364 | that material) supplement the terms of this License with terms:
365 |
366 | a) Disclaiming warranty or limiting liability differently from the
367 | terms of sections 15 and 16 of this License; or
368 |
369 | b) Requiring preservation of specified reasonable legal notices or
370 | author attributions in that material or in the Appropriate Legal
371 | Notices displayed by works containing it; or
372 |
373 | c) Prohibiting misrepresentation of the origin of that material, or
374 | requiring that modified versions of such material be marked in
375 | reasonable ways as different from the original version; or
376 |
377 | d) Limiting the use for publicity purposes of names of licensors or
378 | authors of the material; or
379 |
380 | e) Declining to grant rights under trademark law for use of some
381 | trade names, trademarks, or service marks; or
382 |
383 | f) Requiring indemnification of licensors and authors of that
384 | material by anyone who conveys the material (or modified versions of
385 | it) with contractual assumptions of liability to the recipient, for
386 | any liability that these contractual assumptions directly impose on
387 | those licensors and authors.
388 |
389 | All other non-permissive additional terms are considered "further
390 | restrictions" within the meaning of section 10. If the Program as you
391 | received it, or any part of it, contains a notice stating that it is
392 | governed by this License along with a term that is a further
393 | restriction, you may remove that term. If a license document contains
394 | a further restriction but permits relicensing or conveying under this
395 | License, you may add to a covered work material governed by the terms
396 | of that license document, provided that the further restriction does
397 | not survive such relicensing or conveying.
398 |
399 | If you add terms to a covered work in accord with this section, you
400 | must place, in the relevant source files, a statement of the
401 | additional terms that apply to those files, or a notice indicating
402 | where to find the applicable terms.
403 |
404 | Additional terms, permissive or non-permissive, may be stated in the
405 | form of a separately written license, or stated as exceptions;
406 | the above requirements apply either way.
407 |
408 | 8. Termination.
409 |
410 | You may not propagate or modify a covered work except as expressly
411 | provided under this License. Any attempt otherwise to propagate or
412 | modify it is void, and will automatically terminate your rights under
413 | this License (including any patent licenses granted under the third
414 | paragraph of section 11).
415 |
416 | However, if you cease all violation of this License, then your
417 | license from a particular copyright holder is reinstated (a)
418 | provisionally, unless and until the copyright holder explicitly and
419 | finally terminates your license, and (b) permanently, if the copyright
420 | holder fails to notify you of the violation by some reasonable means
421 | prior to 60 days after the cessation.
422 |
423 | Moreover, your license from a particular copyright holder is
424 | reinstated permanently if the copyright holder notifies you of the
425 | violation by some reasonable means, this is the first time you have
426 | received notice of violation of this License (for any work) from that
427 | copyright holder, and you cure the violation prior to 30 days after
428 | your receipt of the notice.
429 |
430 | Termination of your rights under this section does not terminate the
431 | licenses of parties who have received copies or rights from you under
432 | this License. If your rights have been terminated and not permanently
433 | reinstated, you do not qualify to receive new licenses for the same
434 | material under section 10.
435 |
436 | 9. Acceptance Not Required for Having Copies.
437 |
438 | You are not required to accept this License in order to receive or
439 | run a copy of the Program. Ancillary propagation of a covered work
440 | occurring solely as a consequence of using peer-to-peer transmission
441 | to receive a copy likewise does not require acceptance. However,
442 | nothing other than this License grants you permission to propagate or
443 | modify any covered work. These actions infringe copyright if you do
444 | not accept this License. Therefore, by modifying or propagating a
445 | covered work, you indicate your acceptance of this License to do so.
446 |
447 | 10. Automatic Licensing of Downstream Recipients.
448 |
449 | Each time you convey a covered work, the recipient automatically
450 | receives a license from the original licensors, to run, modify and
451 | propagate that work, subject to this License. You are not responsible
452 | for enforcing compliance by third parties with this License.
453 |
454 | An "entity transaction" is a transaction transferring control of an
455 | organization, or substantially all assets of one, or subdividing an
456 | organization, or merging organizations. If propagation of a covered
457 | work results from an entity transaction, each party to that
458 | transaction who receives a copy of the work also receives whatever
459 | licenses to the work the party's predecessor in interest had or could
460 | give under the previous paragraph, plus a right to possession of the
461 | Corresponding Source of the work from the predecessor in interest, if
462 | the predecessor has it or can get it with reasonable efforts.
463 |
464 | You may not impose any further restrictions on the exercise of the
465 | rights granted or affirmed under this License. For example, you may
466 | not impose a license fee, royalty, or other charge for exercise of
467 | rights granted under this License, and you may not initiate litigation
468 | (including a cross-claim or counterclaim in a lawsuit) alleging that
469 | any patent claim is infringed by making, using, selling, offering for
470 | sale, or importing the Program or any portion of it.
471 |
472 | 11. Patents.
473 |
474 | A "contributor" is a copyright holder who authorizes use under this
475 | License of the Program or a work on which the Program is based. The
476 | work thus licensed is called the contributor's "contributor version".
477 |
478 | A contributor's "essential patent claims" are all patent claims
479 | owned or controlled by the contributor, whether already acquired or
480 | hereafter acquired, that would be infringed by some manner, permitted
481 | by this License, of making, using, or selling its contributor version,
482 | but do not include claims that would be infringed only as a
483 | consequence of further modification of the contributor version. For
484 | purposes of this definition, "control" includes the right to grant
485 | patent sublicenses in a manner consistent with the requirements of
486 | this License.
487 |
488 | Each contributor grants you a non-exclusive, worldwide, royalty-free
489 | patent license under the contributor's essential patent claims, to
490 | make, use, sell, offer for sale, import and otherwise run, modify and
491 | propagate the contents of its contributor version.
492 |
493 | In the following three paragraphs, a "patent license" is any express
494 | agreement or commitment, however denominated, not to enforce a patent
495 | (such as an express permission to practice a patent or covenant not to
496 | sue for patent infringement). To "grant" such a patent license to a
497 | party means to make such an agreement or commitment not to enforce a
498 | patent against the party.
499 |
500 | If you convey a covered work, knowingly relying on a patent license,
501 | and the Corresponding Source of the work is not available for anyone
502 | to copy, free of charge and under the terms of this License, through a
503 | publicly available network server or other readily accessible means,
504 | then you must either (1) cause the Corresponding Source to be so
505 | available, or (2) arrange to deprive yourself of the benefit of the
506 | patent license for this particular work, or (3) arrange, in a manner
507 | consistent with the requirements of this License, to extend the patent
508 | license to downstream recipients. "Knowingly relying" means you have
509 | actual knowledge that, but for the patent license, your conveying the
510 | covered work in a country, or your recipient's use of the covered work
511 | in a country, would infringe one or more identifiable patents in that
512 | country that you have reason to believe are valid.
513 |
514 | If, pursuant to or in connection with a single transaction or
515 | arrangement, you convey, or propagate by procuring conveyance of, a
516 | covered work, and grant a patent license to some of the parties
517 | receiving the covered work authorizing them to use, propagate, modify
518 | or convey a specific copy of the covered work, then the patent license
519 | you grant is automatically extended to all recipients of the covered
520 | work and works based on it.
521 |
522 | A patent license is "discriminatory" if it does not include within
523 | the scope of its coverage, prohibits the exercise of, or is
524 | conditioned on the non-exercise of one or more of the rights that are
525 | specifically granted under this License. You may not convey a covered
526 | work if you are a party to an arrangement with a third party that is
527 | in the business of distributing software, under which you make payment
528 | to the third party based on the extent of your activity of conveying
529 | the work, and under which the third party grants, to any of the
530 | parties who would receive the covered work from you, a discriminatory
531 | patent license (a) in connection with copies of the covered work
532 | conveyed by you (or copies made from those copies), or (b) primarily
533 | for and in connection with specific products or compilations that
534 | contain the covered work, unless you entered into that arrangement,
535 | or that patent license was granted, prior to 28 March 2007.
536 |
537 | Nothing in this License shall be construed as excluding or limiting
538 | any implied license or other defenses to infringement that may
539 | otherwise be available to you under applicable patent law.
540 |
541 | 12. No Surrender of Others' Freedom.
542 |
543 | If conditions are imposed on you (whether by court order, agreement or
544 | otherwise) that contradict the conditions of this License, they do not
545 | excuse you from the conditions of this License. If you cannot convey a
546 | covered work so as to satisfy simultaneously your obligations under this
547 | License and any other pertinent obligations, then as a consequence you may
548 | not convey it at all. For example, if you agree to terms that obligate you
549 | to collect a royalty for further conveying from those to whom you convey
550 | the Program, the only way you could satisfy both those terms and this
551 | License would be to refrain entirely from conveying the Program.
552 |
553 | 13. Use with the GNU Affero General Public License.
554 |
555 | Notwithstanding any other provision of this License, you have
556 | permission to link or combine any covered work with a work licensed
557 | under version 3 of the GNU Affero General Public License into a single
558 | combined work, and to convey the resulting work. The terms of this
559 | License will continue to apply to the part which is the covered work,
560 | but the special requirements of the GNU Affero General Public License,
561 | section 13, concerning interaction through a network will apply to the
562 | combination as such.
563 |
564 | 14. Revised Versions of this License.
565 |
566 | The Free Software Foundation may publish revised and/or new versions of
567 | the GNU General Public License from time to time. Such new versions will
568 | be similar in spirit to the present version, but may differ in detail to
569 | address new problems or concerns.
570 |
571 | Each version is given a distinguishing version number. If the
572 | Program specifies that a certain numbered version of the GNU General
573 | Public License "or any later version" applies to it, you have the
574 | option of following the terms and conditions either of that numbered
575 | version or of any later version published by the Free Software
576 | Foundation. If the Program does not specify a version number of the
577 | GNU General Public License, you may choose any version ever published
578 | by the Free Software Foundation.
579 |
580 | If the Program specifies that a proxy can decide which future
581 | versions of the GNU General Public License can be used, that proxy's
582 | public statement of acceptance of a version permanently authorizes you
583 | to choose that version for the Program.
584 |
585 | Later license versions may give you additional or different
586 | permissions. However, no additional obligations are imposed on any
587 | author or copyright holder as a result of your choosing to follow a
588 | later version.
589 |
590 | 15. Disclaimer of Warranty.
591 |
592 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
593 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
594 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
595 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
596 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
597 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
598 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
599 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
600 |
601 | 16. Limitation of Liability.
602 |
603 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
604 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
605 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
606 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
607 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
608 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
609 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
610 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
611 | SUCH DAMAGES.
612 |
613 | 17. Interpretation of Sections 15 and 16.
614 |
615 | If the disclaimer of warranty and limitation of liability provided
616 | above cannot be given local legal effect according to their terms,
617 | reviewing courts shall apply local law that most closely approximates
618 | an absolute waiver of all civil liability in connection with the
619 | Program, unless a warranty or assumption of liability accompanies a
620 | copy of the Program in return for a fee.
621 |
622 | END OF TERMS AND CONDITIONS
623 |
624 | How to Apply These Terms to Your New Programs
625 |
626 | If you develop a new program, and you want it to be of the greatest
627 | possible use to the public, the best way to achieve this is to make it
628 | free software which everyone can redistribute and change under these terms.
629 |
630 | To do so, attach the following notices to the program. It is safest
631 | to attach them to the start of each source file to most effectively
632 | state the exclusion of warranty; and each file should have at least
633 | the "copyright" line and a pointer to where the full notice is found.
634 |
635 |
636 | Copyright (C)
637 |
638 | This program is free software: you can redistribute it and/or modify
639 | it under the terms of the GNU General Public License as published by
640 | the Free Software Foundation, either version 3 of the License, or
641 | (at your option) any later version.
642 |
643 | This program is distributed in the hope that it will be useful,
644 | but WITHOUT ANY WARRANTY; without even the implied warranty of
645 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
646 | GNU General Public License for more details.
647 |
648 | You should have received a copy of the GNU General Public License
649 | along with this program. If not, see .
650 |
651 | Also add information on how to contact you by electronic and paper mail.
652 |
653 | If the program does terminal interaction, make it output a short
654 | notice like this when it starts in an interactive mode:
655 |
656 | Copyright (C)
657 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
658 | This is free software, and you are welcome to redistribute it
659 | under certain conditions; type `show c' for details.
660 |
661 | The hypothetical commands `show w' and `show c' should show the appropriate
662 | parts of the General Public License. Of course, your program's commands
663 | might be different; for a GUI interface, you would use an "about box".
664 |
665 | You should also get your employer (if you work as a programmer) or school,
666 | if any, to sign a "copyright disclaimer" for the program, if necessary.
667 | For more information on this, and how to apply and follow the GNU GPL, see
668 | .
669 |
670 | The GNU General Public License does not permit incorporating your program
671 | into proprietary programs. If your program is a subroutine library, you
672 | may consider it more useful to permit linking proprietary applications with
673 | the library. If this is what you want to do, use the GNU Lesser General
674 | Public License instead of this License. But first, please read
675 | .
676 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TinyGPSPlus-ESP32
2 |
3 | A new, customizable Arduino NMEA parsing library
4 | A *NEW* Full-featured GPS/NMEA Parser for Arduino
5 | TinyGPSPlus is a new Arduino library for parsing NMEA data streams provided by GPS modules.
6 |
7 | Like its predecessor, TinyGPS, this library provides compact and easy-to-use methods for extracting position, date, time, altitude, speed, and course from consumer GPS devices.
8 |
9 | However, TinyGPSPlus’s programmer interface is considerably simpler to use than TinyGPS, and the new library can extract arbitrary data from any of the myriad NMEA sentences out there, even proprietary ones.
10 |
11 | See [Arduiniana - TinyGPSPlus](http://arduiniana.org/libraries/tinygpsplus/) for more detailed information on how to use TinyGPSPlus
12 |
--------------------------------------------------------------------------------
/examples/BasicExample/BasicExample.ino:
--------------------------------------------------------------------------------
1 | #include
2 | /*
3 | This sample sketch should be the first you try out when you are testing a TinyGPSPlus
4 | (TinyGPSPlus) installation. In normal use, you feed TinyGPSPlus objects characters from
5 | a serial NMEA GPS device, but this example uses static strings for simplicity.
6 | */
7 |
8 | // A sample NMEA stream.
9 | const char *gpsStream =
10 | "$GPRMC,045103.000,A,3014.1984,N,09749.2872,W,0.67,161.46,030913,,,A*7C\r\n"
11 | "$GPGGA,045104.000,3014.1985,N,09749.2873,W,1,09,1.2,211.6,M,-22.5,M,,0000*62\r\n"
12 | "$GPRMC,045200.000,A,3014.3820,N,09748.9514,W,36.88,65.02,030913,,,A*77\r\n"
13 | "$GPGGA,045201.000,3014.3864,N,09748.9411,W,1,10,1.2,200.8,M,-22.5,M,,0000*6C\r\n"
14 | "$GPRMC,045251.000,A,3014.4275,N,09749.0626,W,0.51,217.94,030913,,,A*7D\r\n"
15 | "$GPGGA,045252.000,3014.4273,N,09749.0628,W,1,09,1.3,206.9,M,-22.5,M,,0000*6F\r\n";
16 |
17 | // The TinyGPSPlus object
18 | TinyGPSPlus gps;
19 |
20 | void setup()
21 | {
22 | Serial.begin(115200);
23 |
24 | Serial.println(F("BasicExample.ino"));
25 | Serial.println(F("Basic demonstration of TinyGPSPlus (no device needed)"));
26 | Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
27 | Serial.println(F("by Mikal Hart"));
28 | Serial.println();
29 |
30 | while (*gpsStream)
31 | if (gps.encode(*gpsStream++))
32 | displayInfo();
33 |
34 | Serial.println();
35 | Serial.println(F("Done."));
36 | }
37 |
38 | void loop()
39 | {
40 | }
41 |
42 | void displayInfo()
43 | {
44 | Serial.print(F("Location: "));
45 | if (gps.location.isValid())
46 | {
47 | Serial.print(gps.location.lat(), 6);
48 | Serial.print(F(","));
49 | Serial.print(gps.location.lng(), 6);
50 | }
51 | else
52 | {
53 | Serial.print(F("INVALID"));
54 | }
55 |
56 | Serial.print(F(" Date/Time: "));
57 | if (gps.date.isValid())
58 | {
59 | Serial.print(gps.date.month());
60 | Serial.print(F("/"));
61 | Serial.print(gps.date.day());
62 | Serial.print(F("/"));
63 | Serial.print(gps.date.year());
64 | }
65 | else
66 | {
67 | Serial.print(F("INVALID"));
68 | }
69 |
70 | Serial.print(F(" "));
71 | if (gps.time.isValid())
72 | {
73 | if (gps.time.hour() < 10) Serial.print(F("0"));
74 | Serial.print(gps.time.hour());
75 | Serial.print(F(":"));
76 | if (gps.time.minute() < 10) Serial.print(F("0"));
77 | Serial.print(gps.time.minute());
78 | Serial.print(F(":"));
79 | if (gps.time.second() < 10) Serial.print(F("0"));
80 | Serial.print(gps.time.second());
81 | Serial.print(F("."));
82 | if (gps.time.centisecond() < 10) Serial.print(F("0"));
83 | Serial.print(gps.time.centisecond());
84 | }
85 | else
86 | {
87 | Serial.print(F("INVALID"));
88 | }
89 |
90 | Serial.println();
91 | }
92 |
--------------------------------------------------------------------------------
/examples/DeviceExample/DeviceExample.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | /*
4 | This sample sketch demonstrates the normal use of a TinyGPSPlus (TinyGPSPlus) object.
5 | It requires the use of SoftwareSerial, and assumes that you have a
6 | 4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
7 | */
8 | static const int RXPin = 4, TXPin = 3;
9 | static const uint32_t GPSBaud = 4800;
10 |
11 | // The TinyGPSPlus object
12 | TinyGPSPlus gps;
13 |
14 | // The serial connection to the GPS device
15 | SoftwareSerial ss(RXPin, TXPin);
16 |
17 | void setup()
18 | {
19 | Serial.begin(115200);
20 | ss.begin(GPSBaud);
21 |
22 | Serial.println(F("DeviceExample.ino"));
23 | Serial.println(F("A simple demonstration of TinyGPSPlus with an attached GPS module"));
24 | Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
25 | Serial.println(F("by Mikal Hart"));
26 | Serial.println();
27 | }
28 |
29 | void loop()
30 | {
31 | // This sketch displays information every time a new sentence is correctly encoded.
32 | while (ss.available() > 0)
33 | if (gps.encode(ss.read()))
34 | displayInfo();
35 |
36 | if (millis() > 5000 && gps.charsProcessed() < 10)
37 | {
38 | Serial.println(F("No GPS detected: check wiring."));
39 | while(true);
40 | }
41 | }
42 |
43 | void displayInfo()
44 | {
45 | Serial.print(F("Location: "));
46 | if (gps.location.isValid())
47 | {
48 | Serial.print(gps.location.lat(), 6);
49 | Serial.print(F(","));
50 | Serial.print(gps.location.lng(), 6);
51 | }
52 | else
53 | {
54 | Serial.print(F("INVALID"));
55 | }
56 |
57 | Serial.print(F(" Date/Time: "));
58 | if (gps.date.isValid())
59 | {
60 | Serial.print(gps.date.month());
61 | Serial.print(F("/"));
62 | Serial.print(gps.date.day());
63 | Serial.print(F("/"));
64 | Serial.print(gps.date.year());
65 | }
66 | else
67 | {
68 | Serial.print(F("INVALID"));
69 | }
70 |
71 | Serial.print(F(" "));
72 | if (gps.time.isValid())
73 | {
74 | if (gps.time.hour() < 10) Serial.print(F("0"));
75 | Serial.print(gps.time.hour());
76 | Serial.print(F(":"));
77 | if (gps.time.minute() < 10) Serial.print(F("0"));
78 | Serial.print(gps.time.minute());
79 | Serial.print(F(":"));
80 | if (gps.time.second() < 10) Serial.print(F("0"));
81 | Serial.print(gps.time.second());
82 | Serial.print(F("."));
83 | if (gps.time.centisecond() < 10) Serial.print(F("0"));
84 | Serial.print(gps.time.centisecond());
85 | }
86 | else
87 | {
88 | Serial.print(F("INVALID"));
89 | }
90 |
91 | Serial.println();
92 | }
93 |
--------------------------------------------------------------------------------
/examples/FullExample/FullExample.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | /*
4 | This sample code demonstrates the normal use of a TinyGPSPlus (TinyGPSPlus) object.
5 | It requires the use of SoftwareSerial, and assumes that you have a
6 | 4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
7 | */
8 | static const int RXPin = 4, TXPin = 3;
9 | static const uint32_t GPSBaud = 4800;
10 |
11 | // The TinyGPSPlus object
12 | TinyGPSPlus gps;
13 |
14 | // The serial connection to the GPS device
15 | SoftwareSerial ss(RXPin, TXPin);
16 |
17 | void setup()
18 | {
19 | Serial.begin(115200);
20 | ss.begin(GPSBaud);
21 |
22 | Serial.println(F("FullExample.ino"));
23 | Serial.println(F("An extensive example of many interesting TinyGPSPlus features"));
24 | Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
25 | Serial.println(F("by Mikal Hart"));
26 | Serial.println();
27 | Serial.println(F("Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum"));
28 | Serial.println(F(" (deg) (deg) Age Age (m) --- from GPS ---- ---- to London ---- RX RX Fail"));
29 | Serial.println(F("----------------------------------------------------------------------------------------------------------------------------------------"));
30 | }
31 |
32 | void loop()
33 | {
34 | static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
35 |
36 | printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
37 | printFloat(gps.hdop.hdop(), gps.hdop.isValid(), 6, 1);
38 | printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
39 | printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
40 | printInt(gps.location.age(), gps.location.isValid(), 5);
41 | printDateTime(gps.date, gps.time);
42 | printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
43 | printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
44 | printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
45 | printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.deg()) : "*** ", 6);
46 |
47 | unsigned long distanceKmToLondon =
48 | (unsigned long)TinyGPSPlus::distanceBetween(
49 | gps.location.lat(),
50 | gps.location.lng(),
51 | LONDON_LAT,
52 | LONDON_LON) / 1000;
53 | printInt(distanceKmToLondon, gps.location.isValid(), 9);
54 |
55 | double courseToLondon =
56 | TinyGPSPlus::courseTo(
57 | gps.location.lat(),
58 | gps.location.lng(),
59 | LONDON_LAT,
60 | LONDON_LON);
61 |
62 | printFloat(courseToLondon, gps.location.isValid(), 7, 2);
63 |
64 | const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);
65 |
66 | printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);
67 |
68 | printInt(gps.charsProcessed(), true, 6);
69 | printInt(gps.sentencesWithFix(), true, 10);
70 | printInt(gps.failedChecksum(), true, 9);
71 | Serial.println();
72 |
73 | smartDelay(1000);
74 |
75 | if (millis() > 5000 && gps.charsProcessed() < 10)
76 | Serial.println(F("No GPS data received: check wiring"));
77 | }
78 |
79 | // This custom version of delay() ensures that the gps object
80 | // is being "fed".
81 | static void smartDelay(unsigned long ms)
82 | {
83 | unsigned long start = millis();
84 | do
85 | {
86 | while (ss.available())
87 | gps.encode(ss.read());
88 | } while (millis() - start < ms);
89 | }
90 |
91 | static void printFloat(float val, bool valid, int len, int prec)
92 | {
93 | if (!valid)
94 | {
95 | while (len-- > 1)
96 | Serial.print('*');
97 | Serial.print(' ');
98 | }
99 | else
100 | {
101 | Serial.print(val, prec);
102 | int vi = abs((int)val);
103 | int flen = prec + (val < 0.0 ? 2 : 1); // . and -
104 | flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
105 | for (int i=flen; i 0)
120 | sz[len-1] = ' ';
121 | Serial.print(sz);
122 | smartDelay(0);
123 | }
124 |
125 | static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
126 | {
127 | if (!d.isValid())
128 | {
129 | Serial.print(F("********** "));
130 | }
131 | else
132 | {
133 | char sz[32];
134 | sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
135 | Serial.print(sz);
136 | }
137 |
138 | if (!t.isValid())
139 | {
140 | Serial.print(F("******** "));
141 | }
142 | else
143 | {
144 | char sz[32];
145 | sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
146 | Serial.print(sz);
147 | }
148 |
149 | printInt(d.age(), d.isValid(), 5);
150 | smartDelay(0);
151 | }
152 |
153 | static void printStr(const char *str, int len)
154 | {
155 | int slen = strlen(str);
156 | for (int i=0; i
2 | #include
3 | /*
4 | This sample code demonstrates just about every built-in operation of TinyGPSPlus (TinyGPSPlus).
5 | It requires the use of SoftwareSerial, and assumes that you have a
6 | 4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
7 | */
8 | static const int RXPin = 4, TXPin = 3;
9 | static const uint32_t GPSBaud = 4800;
10 |
11 | // The TinyGPSPlus object
12 | TinyGPSPlus gps;
13 |
14 | // The serial connection to the GPS device
15 | SoftwareSerial ss(RXPin, TXPin);
16 |
17 | // For stats that happen every 5 seconds
18 | unsigned long last = 0UL;
19 |
20 | void setup()
21 | {
22 | Serial.begin(115200);
23 | ss.begin(GPSBaud);
24 |
25 | Serial.println(F("KitchenSink.ino"));
26 | Serial.println(F("Demonstrating nearly every feature of TinyGPSPlus"));
27 | Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
28 | Serial.println(F("by Mikal Hart"));
29 | Serial.println();
30 | }
31 |
32 | void loop()
33 | {
34 | // Dispatch incoming characters
35 | while (ss.available() > 0)
36 | gps.encode(ss.read());
37 |
38 | if (gps.location.isUpdated())
39 | {
40 | Serial.print(F("LOCATION Fix Age="));
41 | Serial.print(gps.location.age());
42 | Serial.print(F("ms Raw Lat="));
43 | Serial.print(gps.location.rawLat().negative ? "-" : "+");
44 | Serial.print(gps.location.rawLat().deg);
45 | Serial.print("[+");
46 | Serial.print(gps.location.rawLat().billionths);
47 | Serial.print(F(" billionths], Raw Long="));
48 | Serial.print(gps.location.rawLng().negative ? "-" : "+");
49 | Serial.print(gps.location.rawLng().deg);
50 | Serial.print("[+");
51 | Serial.print(gps.location.rawLng().billionths);
52 | Serial.print(F(" billionths], Lat="));
53 | Serial.print(gps.location.lat(), 6);
54 | Serial.print(F(" Long="));
55 | Serial.println(gps.location.lng(), 6);
56 | }
57 |
58 | else if (gps.date.isUpdated())
59 | {
60 | Serial.print(F("DATE Fix Age="));
61 | Serial.print(gps.date.age());
62 | Serial.print(F("ms Raw="));
63 | Serial.print(gps.date.value());
64 | Serial.print(F(" Year="));
65 | Serial.print(gps.date.year());
66 | Serial.print(F(" Month="));
67 | Serial.print(gps.date.month());
68 | Serial.print(F(" Day="));
69 | Serial.println(gps.date.day());
70 | }
71 |
72 | else if (gps.time.isUpdated())
73 | {
74 | Serial.print(F("TIME Fix Age="));
75 | Serial.print(gps.time.age());
76 | Serial.print(F("ms Raw="));
77 | Serial.print(gps.time.value());
78 | Serial.print(F(" Hour="));
79 | Serial.print(gps.time.hour());
80 | Serial.print(F(" Minute="));
81 | Serial.print(gps.time.minute());
82 | Serial.print(F(" Second="));
83 | Serial.print(gps.time.second());
84 | Serial.print(F(" Hundredths="));
85 | Serial.println(gps.time.centisecond());
86 | }
87 |
88 | else if (gps.speed.isUpdated())
89 | {
90 | Serial.print(F("SPEED Fix Age="));
91 | Serial.print(gps.speed.age());
92 | Serial.print(F("ms Raw="));
93 | Serial.print(gps.speed.value());
94 | Serial.print(F(" Knots="));
95 | Serial.print(gps.speed.knots());
96 | Serial.print(F(" MPH="));
97 | Serial.print(gps.speed.mph());
98 | Serial.print(F(" m/s="));
99 | Serial.print(gps.speed.mps());
100 | Serial.print(F(" km/h="));
101 | Serial.println(gps.speed.kmph());
102 | }
103 |
104 | else if (gps.course.isUpdated())
105 | {
106 | Serial.print(F("COURSE Fix Age="));
107 | Serial.print(gps.course.age());
108 | Serial.print(F("ms Raw="));
109 | Serial.print(gps.course.value());
110 | Serial.print(F(" Deg="));
111 | Serial.println(gps.course.deg());
112 | }
113 |
114 | else if (gps.altitude.isUpdated())
115 | {
116 | Serial.print(F("ALTITUDE Fix Age="));
117 | Serial.print(gps.altitude.age());
118 | Serial.print(F("ms Raw="));
119 | Serial.print(gps.altitude.value());
120 | Serial.print(F(" Meters="));
121 | Serial.print(gps.altitude.meters());
122 | Serial.print(F(" Miles="));
123 | Serial.print(gps.altitude.miles());
124 | Serial.print(F(" KM="));
125 | Serial.print(gps.altitude.kilometers());
126 | Serial.print(F(" Feet="));
127 | Serial.println(gps.altitude.feet());
128 | }
129 |
130 | else if (gps.satellites.isUpdated())
131 | {
132 | Serial.print(F("SATELLITES Fix Age="));
133 | Serial.print(gps.satellites.age());
134 | Serial.print(F("ms Value="));
135 | Serial.println(gps.satellites.value());
136 | }
137 |
138 | else if (gps.hdop.isUpdated())
139 | {
140 | Serial.print(F("HDOP Fix Age="));
141 | Serial.print(gps.hdop.age());
142 | Serial.print(F("ms raw="));
143 | Serial.print(gps.hdop.value());
144 | Serial.print(F(" hdop="));
145 | Serial.println(gps.hdop.hdop());
146 | }
147 |
148 | else if (millis() - last > 5000)
149 | {
150 | Serial.println();
151 | if (gps.location.isValid())
152 | {
153 | static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
154 | double distanceToLondon =
155 | TinyGPSPlus::distanceBetween(
156 | gps.location.lat(),
157 | gps.location.lng(),
158 | LONDON_LAT,
159 | LONDON_LON);
160 | double courseToLondon =
161 | TinyGPSPlus::courseTo(
162 | gps.location.lat(),
163 | gps.location.lng(),
164 | LONDON_LAT,
165 | LONDON_LON);
166 |
167 | Serial.print(F("LONDON Distance="));
168 | Serial.print(distanceToLondon/1000, 6);
169 | Serial.print(F(" km Course-to="));
170 | Serial.print(courseToLondon, 6);
171 | Serial.print(F(" degrees ["));
172 | Serial.print(TinyGPSPlus::cardinal(courseToLondon));
173 | Serial.println(F("]"));
174 | }
175 |
176 | Serial.print(F("DIAGS Chars="));
177 | Serial.print(gps.charsProcessed());
178 | Serial.print(F(" Sentences-with-Fix="));
179 | Serial.print(gps.sentencesWithFix());
180 | Serial.print(F(" Failed-checksum="));
181 | Serial.print(gps.failedChecksum());
182 | Serial.print(F(" Passed-checksum="));
183 | Serial.println(gps.passedChecksum());
184 |
185 | if (gps.charsProcessed() < 10)
186 | Serial.println(F("WARNING: No GPS data. Check wiring."));
187 |
188 | last = millis();
189 | Serial.println();
190 | }
191 | }
--------------------------------------------------------------------------------
/examples/SatElevTracker/SatElevTracker.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | /*
4 | This sample code tracks satellite elevations using TinyGPSCustom objects.
5 |
6 | Satellite numbers and elevations are not normally tracked by TinyGPSPlus, but
7 | by using TinyGPSCustom we get around this.
8 |
9 | It requires the use of SoftwareSerial and assumes that you have a
10 | 4800-baud serial GPS device hooked up on pins 4(RX) and 3(TX).
11 | */
12 | static const int RXPin = 4, TXPin = 3;
13 | static const uint32_t GPSBaud = 4800;
14 | static const int MAX_SATELLITES = 40;
15 | static const int PAGE_LENGTH = 40;
16 |
17 | // The TinyGPSPlus object
18 | TinyGPSPlus gps;
19 |
20 | // The serial connection to the GPS device
21 | SoftwareSerial ss(RXPin, TXPin);
22 |
23 | TinyGPSCustom totalGPGSVMessages(gps, "GPGSV", 1); // $GPGSV sentence, first element
24 | TinyGPSCustom messageNumber(gps, "GPGSV", 2); // $GPGSV sentence, second element
25 | TinyGPSCustom satNumber[4]; // to be initialized later
26 | TinyGPSCustom elevation[4];
27 | bool anyChanges = false;
28 | unsigned long linecount = 0;
29 |
30 | struct
31 | {
32 | int elevation;
33 | bool active;
34 | } sats[MAX_SATELLITES];
35 |
36 | void setup()
37 | {
38 | Serial.begin(115200);
39 | ss.begin(GPSBaud);
40 |
41 | Serial.println(F("SatElevTracker.ino"));
42 | Serial.println(F("Displays GPS satellite elevations as they change"));
43 | Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
44 | Serial.println(F("by Mikal Hart"));
45 | Serial.println();
46 |
47 | // Initialize all the uninitialized TinyGPSCustom objects
48 | for (int i=0; i<4; ++i)
49 | {
50 | satNumber[i].begin(gps, "GPGSV", 4 + 4 * i); // offsets 4, 8, 12, 16
51 | elevation[i].begin(gps, "GPGSV", 5 + 4 * i); // offsets 5, 9, 13, 17
52 | }
53 | }
54 |
55 | void loop()
56 | {
57 | // Dispatch incoming characters
58 | if (ss.available() > 0)
59 | {
60 | gps.encode(ss.read());
61 |
62 | if (totalGPGSVMessages.isUpdated())
63 | {
64 | for (int i=0; i<4; ++i)
65 | {
66 | int no = atoi(satNumber[i].value());
67 | if (no >= 1 && no <= MAX_SATELLITES)
68 | {
69 | int elev = atoi(elevation[i].value());
70 | sats[no-1].active = true;
71 | if (sats[no-1].elevation != elev)
72 | {
73 | sats[no-1].elevation = elev;
74 | anyChanges = true;
75 | }
76 | }
77 | }
78 |
79 | int totalMessages = atoi(totalGPGSVMessages.value());
80 | int currentMessage = atoi(messageNumber.value());
81 | if (totalMessages == currentMessage && anyChanges)
82 | {
83 | if (linecount++ % PAGE_LENGTH == 0)
84 | printHeader();
85 | TimePrint();
86 | for (int i=0; i
2 | #include
3 | /*
4 | This sample code demonstrates how to use an array of TinyGPSCustom objects
5 | to monitor all the visible satellites.
6 |
7 | Satellite numbers, elevation, azimuth, and signal-to-noise ratio are not
8 | normally tracked by TinyGPSPlus, but by using TinyGPSCustom we get around this.
9 |
10 | The simple code also demonstrates how to use arrays of TinyGPSCustom objects,
11 | each monitoring a different field of the $GPGSV sentence.
12 |
13 | It requires the use of SoftwareSerial, and assumes that you have a
14 | 4800-baud serial GPS device hooked up on pins 4(RX) and 3(TX).
15 | */
16 | static const int RXPin = 4, TXPin = 3;
17 | static const uint32_t GPSBaud = 4800;
18 |
19 | // The TinyGPSPlus object
20 | TinyGPSPlus gps;
21 |
22 | // The serial connection to the GPS device
23 | SoftwareSerial ss(RXPin, TXPin);
24 |
25 | /*
26 | From http://aprs.gids.nl/nmea/:
27 |
28 | $GPGSV
29 |
30 | GPS Satellites in view
31 |
32 | eg. $GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74
33 | $GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74
34 | $GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D
35 |
36 | 1 = Total number of messages of this type in this cycle
37 | 2 = Message number
38 | 3 = Total number of SVs in view
39 | 4 = SV PRN number
40 | 5 = Elevation in degrees, 90 maximum
41 | 6 = Azimuth, degrees from true north, 000 to 359
42 | 7 = SNR, 00-99 dB (null when not tracking)
43 | 8-11 = Information about second SV, same as field 4-7
44 | 12-15= Information about third SV, same as field 4-7
45 | 16-19= Information about fourth SV, same as field 4-7
46 | */
47 |
48 | static const int MAX_SATELLITES = 40;
49 |
50 | TinyGPSCustom totalGPGSVMessages(gps, "GPGSV", 1); // $GPGSV sentence, first element
51 | TinyGPSCustom messageNumber(gps, "GPGSV", 2); // $GPGSV sentence, second element
52 | TinyGPSCustom satsInView(gps, "GPGSV", 3); // $GPGSV sentence, third element
53 | TinyGPSCustom satNumber[4]; // to be initialized later
54 | TinyGPSCustom elevation[4];
55 | TinyGPSCustom azimuth[4];
56 | TinyGPSCustom snr[4];
57 |
58 | struct
59 | {
60 | bool active;
61 | int elevation;
62 | int azimuth;
63 | int snr;
64 | } sats[MAX_SATELLITES];
65 |
66 | void setup()
67 | {
68 | Serial.begin(115200);
69 | ss.begin(GPSBaud);
70 |
71 | Serial.println(F("SatelliteTracker.ino"));
72 | Serial.println(F("Monitoring satellite location and signal strength using TinyGPSCustom"));
73 | Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
74 | Serial.println(F("by Mikal Hart"));
75 | Serial.println();
76 |
77 | // Initialize all the uninitialized TinyGPSCustom objects
78 | for (int i=0; i<4; ++i)
79 | {
80 | satNumber[i].begin(gps, "GPGSV", 4 + 4 * i); // offsets 4, 8, 12, 16
81 | elevation[i].begin(gps, "GPGSV", 5 + 4 * i); // offsets 5, 9, 13, 17
82 | azimuth[i].begin( gps, "GPGSV", 6 + 4 * i); // offsets 6, 10, 14, 18
83 | snr[i].begin( gps, "GPGSV", 7 + 4 * i); // offsets 7, 11, 15, 19
84 | }
85 | }
86 |
87 | void loop()
88 | {
89 | // Dispatch incoming characters
90 | if (ss.available() > 0)
91 | {
92 | gps.encode(ss.read());
93 | if (totalGPGSVMessages.isUpdated())
94 | {
95 | for (int i=0; i<4; ++i)
96 | {
97 | int no = atoi(satNumber[i].value());
98 | // Serial.print(F("SatNumber is ")); Serial.println(no);
99 | if (no >= 1 && no <= MAX_SATELLITES)
100 | {
101 | sats[no-1].elevation = atoi(elevation[i].value());
102 | sats[no-1].azimuth = atoi(azimuth[i].value());
103 | sats[no-1].snr = atoi(snr[i].value());
104 | sats[no-1].active = true;
105 | }
106 | }
107 |
108 | int totalMessages = atoi(totalGPGSVMessages.value());
109 | int currentMessage = atoi(messageNumber.value());
110 | if (totalMessages == currentMessage)
111 | {
112 | Serial.print(F("Sats=")); Serial.print(gps.satellites.value());
113 | Serial.print(F(" Nums="));
114 | for (int i=0; i
2 | #include
3 |
4 | /*
5 | This sample demonstrates TinyGPSPlus's capacity for extracting custom
6 | fields from any NMEA sentence. TinyGPSPlus has built-in facilities for
7 | extracting latitude, longitude, altitude, etc., from the $GPGGA and
8 | $GPRMC sentences. But with the TinyGPSCustom type, you can extract
9 | other NMEA fields, even from non-standard NMEA sentences.
10 |
11 | It requires the use of SoftwareSerial, and assumes that you have a
12 | 4800-baud serial GPS device hooked up on pins 4(RX) and 3(TX).
13 | */
14 | static const int RXPin = 4, TXPin = 3;
15 | static const uint32_t GPSBaud = 4800;
16 |
17 | // The TinyGPSPlus object
18 | TinyGPSPlus gps;
19 |
20 | // The serial connection to the GPS device
21 | SoftwareSerial ss(RXPin, TXPin);
22 |
23 | /*
24 | By declaring TinyGPSCustom objects like this, we announce that we
25 | are interested in the 15th, 16th, and 17th fields in the $GPGSA
26 | sentence, respectively the PDOP (F("positional dilution of precision")),
27 | HDOP (F("horizontal...")), and VDOP (F("vertical...")).
28 |
29 | (Counting starts with the field immediately following the sentence name,
30 | i.e. $GPGSA. For more information on NMEA sentences, consult your
31 | GPS module's documentation and/or http://aprs.gids.nl/nmea/.)
32 |
33 | If your GPS module doesn't support the $GPGSA sentence, then you
34 | won't get any output from this program.
35 | */
36 |
37 | TinyGPSCustom pdop(gps, "GPGSA", 15); // $GPGSA sentence, 15th element
38 | TinyGPSCustom hdop(gps, "GPGSA", 16); // $GPGSA sentence, 16th element
39 | TinyGPSCustom vdop(gps, "GPGSA", 17); // $GPGSA sentence, 17th element
40 |
41 | void setup()
42 | {
43 | Serial.begin(115200);
44 | ss.begin(GPSBaud);
45 |
46 | Serial.println(F("UsingCustomFields.ino"));
47 | Serial.println(F("Demonstrating how to extract any NMEA field using TinyGPSCustom"));
48 | Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
49 | Serial.println(F("by Mikal Hart"));
50 | Serial.println();
51 | }
52 |
53 | void loop()
54 | {
55 | // Every time anything is updated, print everything.
56 | if (gps.altitude.isUpdated() || gps.satellites.isUpdated() ||
57 | pdop.isUpdated() || hdop.isUpdated() || vdop.isUpdated())
58 | {
59 | Serial.print(F("ALT=")); Serial.print(gps.altitude.meters());
60 | Serial.print(F(" PDOP=")); Serial.print(pdop.value());
61 | Serial.print(F(" HDOP=")); Serial.print(hdop.value());
62 | Serial.print(F(" VDOP=")); Serial.print(vdop.value());
63 | Serial.print(F(" SATS=")); Serial.println(gps.satellites.value());
64 | }
65 |
66 | while (ss.available() > 0)
67 | gps.encode(ss.read());
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/library.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "TinyGPSPlus-ESP32",
3 | "description": "A new, customizable Arduino NMEA parsing library",
4 | "keywords": "gps,NMEA",
5 | "authors": {
6 | "name": "Mikal Hart",
7 | "url": "http://arduiniana.org"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/Tinyu-Zhao/TinyGPSPlus-ESP32.git"
12 | },
13 | "version": "0.0.2",
14 | "frameworks": "arduino",
15 | "platforms": "*"
16 | }
17 |
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=TinyGPSPlus-ESP32
2 | version=0.0.2
3 | author=Mikal Hart
4 | maintainer=Mikal Hart
5 | sentence=A GPS library
6 | paragraph=A compact Arduino NMEA (GPS) parsing library
7 | category=Device Control
8 | url=https://github.com/Tinyu-Zhao/TinyGPSPlus-ESP32
9 | architectures=esp32
10 |
--------------------------------------------------------------------------------
/src/TinyGPSPlus.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | TinyGPSPlus - a small GPS library for Arduino providing universal NMEA parsing
3 | Based on work by and "distanceBetween" and "courseTo" courtesy of Maarten Lamers.
4 | Suggestion to add satellites, courseTo(), and cardinal() by Matt Monson.
5 | Location precision improvements suggested by Wayne Holder.
6 | Copyright (C) 2008-2013 Mikal Hart
7 | All rights reserved.
8 |
9 | This library is free software; you can redistribute it and/or
10 | modify it under the terms of the GNU Lesser General Public
11 | License as published by the Free Software Foundation; either
12 | version 2.1 of the License, or (at your option) any later version.
13 |
14 | This library is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | Lesser General Public License for more details.
18 |
19 | You should have received a copy of the GNU Lesser General Public
20 | License along with this library; if not, write to the Free Software
21 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 | */
23 |
24 | #include "TinyGPSPlus.h"
25 |
26 | #include
27 | #include
28 | #include
29 |
30 | #define _GPRMCterm "GPRMC"
31 | #define _GPGGAterm "GPGGA"
32 | #define _GNRMCterm "GNRMC"
33 | #define _GNGGAterm "GNGGA"
34 |
35 | TinyGPSPlus::TinyGPSPlus()
36 | : parity(0)
37 | , isChecksumTerm(false)
38 | , curSentenceType(GPS_SENTENCE_OTHER)
39 | , curTermNumber(0)
40 | , curTermOffset(0)
41 | , sentenceHasFix(false)
42 | , customElts(0)
43 | , customCandidates(0)
44 | , encodedCharCount(0)
45 | , sentencesWithFixCount(0)
46 | , failedChecksumCount(0)
47 | , passedChecksumCount(0)
48 | {
49 | term[0] = '\0';
50 | }
51 |
52 | // public methods
53 | //
54 |
55 | bool TinyGPSPlus::encode(char c)
56 | {
57 | ++encodedCharCount;
58 |
59 | switch(c)
60 | {
61 | case ',': // term terminators
62 | parity ^= (uint8_t)c;
63 | case '\r':
64 | case '\n':
65 | case '*':
66 | {
67 | bool isValidSentence = false;
68 | if (curTermOffset < sizeof(term))
69 | {
70 | term[curTermOffset] = 0;
71 | isValidSentence = endOfTermHandler();
72 | }
73 | ++curTermNumber;
74 | curTermOffset = 0;
75 | isChecksumTerm = c == '*';
76 | return isValidSentence;
77 | }
78 | break;
79 |
80 | case '$': // sentence begin
81 | curTermNumber = curTermOffset = 0;
82 | parity = 0;
83 | curSentenceType = GPS_SENTENCE_OTHER;
84 | isChecksumTerm = false;
85 | sentenceHasFix = false;
86 | return false;
87 |
88 | default: // ordinary characters
89 | if (curTermOffset < sizeof(term) - 1)
90 | term[curTermOffset++] = c;
91 | if (!isChecksumTerm)
92 | parity ^= c;
93 | return false;
94 | }
95 |
96 | return false;
97 | }
98 |
99 | //
100 | // internal utilities
101 | //
102 | int TinyGPSPlus::fromHex(char a)
103 | {
104 | if (a >= 'A' && a <= 'F')
105 | return a - 'A' + 10;
106 | else if (a >= 'a' && a <= 'f')
107 | return a - 'a' + 10;
108 | else
109 | return a - '0';
110 | }
111 |
112 | // static
113 | // Parse a (potentially negative) number with up to 2 decimal digits -xxxx.yy
114 | int32_t TinyGPSPlus::parseDecimal(const char *term)
115 | {
116 | bool negative = *term == '-';
117 | if (negative) ++term;
118 | int32_t ret = 100 * (int32_t)atol(term);
119 | while (isdigit(*term)) ++term;
120 | if (*term == '.' && isdigit(term[1]))
121 | {
122 | ret += 10 * (term[1] - '0');
123 | if (isdigit(term[2]))
124 | ret += term[2] - '0';
125 | }
126 | return negative ? -ret : ret;
127 | }
128 |
129 | // static
130 | // Parse degrees in that funny NMEA format DDMM.MMMM
131 | void TinyGPSPlus::parseDegrees(const char *term, RawDegrees °)
132 | {
133 | uint32_t leftOfDecimal = (uint32_t)atol(term);
134 | uint16_t minutes = (uint16_t)(leftOfDecimal % 100);
135 | uint32_t multiplier = 10000000UL;
136 | uint32_t tenMillionthsOfMinutes = minutes * multiplier;
137 |
138 | deg.deg = (int16_t)(leftOfDecimal / 100);
139 |
140 | while (isdigit(*term))
141 | ++term;
142 |
143 | if (*term == '.')
144 | while (isdigit(*++term))
145 | {
146 | multiplier /= 10;
147 | tenMillionthsOfMinutes += (*term - '0') * multiplier;
148 | }
149 |
150 | deg.billionths = (5 * tenMillionthsOfMinutes + 1) / 3;
151 | deg.negative = false;
152 | }
153 |
154 | #define COMBINE(sentence_type, term_number) (((unsigned)(sentence_type) << 5) | term_number)
155 |
156 | // Processes a just-completed term
157 | // Returns true if new sentence has just passed checksum test and is validated
158 | bool TinyGPSPlus::endOfTermHandler()
159 | {
160 | // If it's the checksum term, and the checksum checks out, commit
161 | if (isChecksumTerm)
162 | {
163 | byte checksum = 16 * fromHex(term[0]) + fromHex(term[1]);
164 | if (checksum == parity)
165 | {
166 | passedChecksumCount++;
167 | if (sentenceHasFix)
168 | ++sentencesWithFixCount;
169 |
170 | switch(curSentenceType)
171 | {
172 | case GPS_SENTENCE_GPRMC:
173 | date.commit();
174 | time.commit();
175 | if (sentenceHasFix)
176 | {
177 | location.commit();
178 | speed.commit();
179 | course.commit();
180 | }
181 | break;
182 | case GPS_SENTENCE_GPGGA:
183 | time.commit();
184 | if (sentenceHasFix)
185 | {
186 | location.commit();
187 | altitude.commit();
188 | }
189 | satellites.commit();
190 | hdop.commit();
191 | break;
192 | }
193 |
194 | // Commit all custom listeners of this sentence type
195 | for (TinyGPSCustom *p = customCandidates; p != NULL && strcmp(p->sentenceName, customCandidates->sentenceName) == 0; p = p->next)
196 | p->commit();
197 | return true;
198 | }
199 |
200 | else
201 | {
202 | ++failedChecksumCount;
203 | }
204 |
205 | return false;
206 | }
207 |
208 | // the first term determines the sentence type
209 | if (curTermNumber == 0)
210 | {
211 | if (!strcmp(term, _GPRMCterm) || !strcmp(term, _GNRMCterm))
212 | curSentenceType = GPS_SENTENCE_GPRMC;
213 | else if (!strcmp(term, _GPGGAterm) || !strcmp(term, _GNGGAterm))
214 | curSentenceType = GPS_SENTENCE_GPGGA;
215 | else
216 | curSentenceType = GPS_SENTENCE_OTHER;
217 |
218 | // Any custom candidates of this sentence type?
219 | for (customCandidates = customElts; customCandidates != NULL && strcmp(customCandidates->sentenceName, term) < 0; customCandidates = customCandidates->next);
220 | if (customCandidates != NULL && strcmp(customCandidates->sentenceName, term) > 0)
221 | customCandidates = NULL;
222 |
223 | return false;
224 | }
225 |
226 | if (curSentenceType != GPS_SENTENCE_OTHER && term[0])
227 | switch(COMBINE(curSentenceType, curTermNumber))
228 | {
229 | case COMBINE(GPS_SENTENCE_GPRMC, 1): // Time in both sentences
230 | case COMBINE(GPS_SENTENCE_GPGGA, 1):
231 | time.setTime(term);
232 | break;
233 | case COMBINE(GPS_SENTENCE_GPRMC, 2): // GPRMC validity
234 | sentenceHasFix = term[0] == 'A';
235 | break;
236 | case COMBINE(GPS_SENTENCE_GPRMC, 3): // Latitude
237 | case COMBINE(GPS_SENTENCE_GPGGA, 2):
238 | location.setLatitude(term);
239 | break;
240 | case COMBINE(GPS_SENTENCE_GPRMC, 4): // N/S
241 | case COMBINE(GPS_SENTENCE_GPGGA, 3):
242 | location.rawNewLatData.negative = term[0] == 'S';
243 | break;
244 | case COMBINE(GPS_SENTENCE_GPRMC, 5): // Longitude
245 | case COMBINE(GPS_SENTENCE_GPGGA, 4):
246 | location.setLongitude(term);
247 | break;
248 | case COMBINE(GPS_SENTENCE_GPRMC, 6): // E/W
249 | case COMBINE(GPS_SENTENCE_GPGGA, 5):
250 | location.rawNewLngData.negative = term[0] == 'W';
251 | break;
252 | case COMBINE(GPS_SENTENCE_GPRMC, 7): // Speed (GPRMC)
253 | speed.set(term);
254 | break;
255 | case COMBINE(GPS_SENTENCE_GPRMC, 8): // Course (GPRMC)
256 | course.set(term);
257 | break;
258 | case COMBINE(GPS_SENTENCE_GPRMC, 9): // Date (GPRMC)
259 | date.setDate(term);
260 | break;
261 | case COMBINE(GPS_SENTENCE_GPGGA, 6): // Fix data (GPGGA)
262 | sentenceHasFix = term[0] > '0';
263 | break;
264 | case COMBINE(GPS_SENTENCE_GPGGA, 7): // Satellites used (GPGGA)
265 | satellites.set(term);
266 | break;
267 | case COMBINE(GPS_SENTENCE_GPGGA, 8): // HDOP
268 | hdop.set(term);
269 | break;
270 | case COMBINE(GPS_SENTENCE_GPGGA, 9): // Altitude (GPGGA)
271 | altitude.set(term);
272 | break;
273 | }
274 |
275 | // Set custom values as needed
276 | for (TinyGPSCustom *p = customCandidates; p != NULL && strcmp(p->sentenceName, customCandidates->sentenceName) == 0 && p->termNumber <= curTermNumber; p = p->next)
277 | if (p->termNumber == curTermNumber)
278 | p->set(term);
279 |
280 | return false;
281 | }
282 |
283 | /* static */
284 | double TinyGPSPlus::distanceBetween(double lat1, double long1, double lat2, double long2)
285 | {
286 | // returns distance in meters between two positions, both specified
287 | // as signed decimal-degrees latitude and longitude. Uses great-circle
288 | // distance computation for hypothetical sphere of radius 6372795 meters.
289 | // Because Earth is no exact sphere, rounding errors may be up to 0.5%.
290 | // Courtesy of Maarten Lamers
291 | double delta = radians(long1-long2);
292 | double sdlong = sin(delta);
293 | double cdlong = cos(delta);
294 | lat1 = radians(lat1);
295 | lat2 = radians(lat2);
296 | double slat1 = sin(lat1);
297 | double clat1 = cos(lat1);
298 | double slat2 = sin(lat2);
299 | double clat2 = cos(lat2);
300 | delta = (clat1 * slat2) - (slat1 * clat2 * cdlong);
301 | delta = sq(delta);
302 | delta += sq(clat2 * sdlong);
303 | delta = sqrt(delta);
304 | double denom = (slat1 * slat2) + (clat1 * clat2 * cdlong);
305 | delta = atan2(delta, denom);
306 | return delta * 6372795;
307 | }
308 |
309 | double TinyGPSPlus::courseTo(double lat1, double long1, double lat2, double long2)
310 | {
311 | // returns course in degrees (North=0, West=270) from position 1 to position 2,
312 | // both specified as signed decimal-degrees latitude and longitude.
313 | // Because Earth is no exact sphere, calculated course may be off by a tiny fraction.
314 | // Courtesy of Maarten Lamers
315 | double dlon = radians(long2-long1);
316 | lat1 = radians(lat1);
317 | lat2 = radians(lat2);
318 | double a1 = sin(dlon) * cos(lat2);
319 | double a2 = sin(lat1) * cos(lat2) * cos(dlon);
320 | a2 = cos(lat1) * sin(lat2) - a2;
321 | a2 = atan2(a1, a2);
322 | if (a2 < 0.0)
323 | {
324 | a2 += TWO_PI;
325 | }
326 | return degrees(a2);
327 | }
328 |
329 | const char *TinyGPSPlus::cardinal(double course)
330 | {
331 | static const char* directions[] = {"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"};
332 | int direction = (int)((course + 11.25f) / 22.5f);
333 | return directions[direction % 16];
334 | }
335 |
336 | void TinyGPSLocation::commit()
337 | {
338 | rawLatData = rawNewLatData;
339 | rawLngData = rawNewLngData;
340 | lastCommitTime = millis();
341 | valid = updated = true;
342 | }
343 |
344 | void TinyGPSLocation::setLatitude(const char *term)
345 | {
346 | TinyGPSPlus::parseDegrees(term, rawNewLatData);
347 | }
348 |
349 | void TinyGPSLocation::setLongitude(const char *term)
350 | {
351 | TinyGPSPlus::parseDegrees(term, rawNewLngData);
352 | }
353 |
354 | double TinyGPSLocation::lat()
355 | {
356 | updated = false;
357 | double ret = rawLatData.deg + rawLatData.billionths / 1000000000.0;
358 | return rawLatData.negative ? -ret : ret;
359 | }
360 |
361 | double TinyGPSLocation::lng()
362 | {
363 | updated = false;
364 | double ret = rawLngData.deg + rawLngData.billionths / 1000000000.0;
365 | return rawLngData.negative ? -ret : ret;
366 | }
367 |
368 | void TinyGPSDate::commit()
369 | {
370 | date = newDate;
371 | lastCommitTime = millis();
372 | valid = updated = true;
373 | }
374 |
375 | void TinyGPSTime::commit()
376 | {
377 | time = newTime;
378 | lastCommitTime = millis();
379 | valid = updated = true;
380 | }
381 |
382 | void TinyGPSTime::setTime(const char *term)
383 | {
384 | newTime = (uint32_t)TinyGPSPlus::parseDecimal(term);
385 | }
386 |
387 | void TinyGPSDate::setDate(const char *term)
388 | {
389 | newDate = atol(term);
390 | }
391 |
392 | uint16_t TinyGPSDate::year()
393 | {
394 | updated = false;
395 | uint16_t year = date % 100;
396 | return year + 2000;
397 | }
398 |
399 | uint8_t TinyGPSDate::month()
400 | {
401 | updated = false;
402 | return (date / 100) % 100;
403 | }
404 |
405 | uint8_t TinyGPSDate::day()
406 | {
407 | updated = false;
408 | return date / 10000;
409 | }
410 |
411 | uint8_t TinyGPSTime::hour()
412 | {
413 | updated = false;
414 | return time / 1000000;
415 | }
416 |
417 | uint8_t TinyGPSTime::minute()
418 | {
419 | updated = false;
420 | return (time / 10000) % 100;
421 | }
422 |
423 | uint8_t TinyGPSTime::second()
424 | {
425 | updated = false;
426 | return (time / 100) % 100;
427 | }
428 |
429 | uint8_t TinyGPSTime::centisecond()
430 | {
431 | updated = false;
432 | return time % 100;
433 | }
434 |
435 | void TinyGPSDecimal::commit()
436 | {
437 | val = newval;
438 | lastCommitTime = millis();
439 | valid = updated = true;
440 | }
441 |
442 | void TinyGPSDecimal::set(const char *term)
443 | {
444 | newval = TinyGPSPlus::parseDecimal(term);
445 | }
446 |
447 | void TinyGPSInteger::commit()
448 | {
449 | val = newval;
450 | lastCommitTime = millis();
451 | valid = updated = true;
452 | }
453 |
454 | void TinyGPSInteger::set(const char *term)
455 | {
456 | newval = atol(term);
457 | }
458 |
459 | TinyGPSCustom::TinyGPSCustom(TinyGPSPlus &gps, const char *_sentenceName, int _termNumber)
460 | {
461 | begin(gps, _sentenceName, _termNumber);
462 | }
463 |
464 | void TinyGPSCustom::begin(TinyGPSPlus &gps, const char *_sentenceName, int _termNumber)
465 | {
466 | lastCommitTime = 0;
467 | updated = valid = false;
468 | sentenceName = _sentenceName;
469 | termNumber = _termNumber;
470 | memset(stagingBuffer, '\0', sizeof(stagingBuffer));
471 | memset(buffer, '\0', sizeof(buffer));
472 |
473 | // Insert this item into the GPS tree
474 | gps.insertCustom(this, _sentenceName, _termNumber);
475 | }
476 |
477 | void TinyGPSCustom::commit()
478 | {
479 | strcpy(this->buffer, this->stagingBuffer);
480 | lastCommitTime = millis();
481 | valid = updated = true;
482 | }
483 |
484 | void TinyGPSCustom::set(const char *term)
485 | {
486 | strncpy(this->stagingBuffer, term, sizeof(this->stagingBuffer));
487 | }
488 |
489 | void TinyGPSPlus::insertCustom(TinyGPSCustom *pElt, const char *sentenceName, int termNumber)
490 | {
491 | TinyGPSCustom **ppelt;
492 |
493 | for (ppelt = &this->customElts; *ppelt != NULL; ppelt = &(*ppelt)->next)
494 | {
495 | int cmp = strcmp(sentenceName, (*ppelt)->sentenceName);
496 | if (cmp < 0 || (cmp == 0 && termNumber < (*ppelt)->termNumber))
497 | break;
498 | }
499 |
500 | pElt->next = *ppelt;
501 | *ppelt = pElt;
502 | }
503 |
--------------------------------------------------------------------------------
/src/TinyGPSPlus.h:
--------------------------------------------------------------------------------
1 | /*
2 | TinyGPSPlus - a small GPS library for Arduino providing universal NMEA parsing
3 | Based on work by and "distanceBetween" and "courseTo" courtesy of Maarten Lamers.
4 | Suggestion to add satellites, courseTo(), and cardinal() by Matt Monson.
5 | Location precision improvements suggested by Wayne Holder.
6 | Copyright (C) 2008-2013 Mikal Hart
7 | All rights reserved.
8 |
9 | This library is free software; you can redistribute it and/or
10 | modify it under the terms of the GNU Lesser General Public
11 | License as published by the Free Software Foundation; either
12 | version 2.1 of the License, or (at your option) any later version.
13 |
14 | This library is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | Lesser General Public License for more details.
18 |
19 | You should have received a copy of the GNU Lesser General Public
20 | License along with this library; if not, write to the Free Software
21 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 | */
23 |
24 | #ifndef __TinyGPSPlus_h
25 | #define __TinyGPSPlus_h
26 |
27 | #if defined(ARDUINO) && ARDUINO >= 100
28 | #include "Arduino.h"
29 | #else
30 | #include "WProgram.h"
31 | #endif
32 | #include
33 |
34 | #define _GPS_VERSION "1.0.2" // software version of this library
35 | #define _GPS_MPH_PER_KNOT 1.15077945
36 | #define _GPS_MPS_PER_KNOT 0.51444444
37 | #define _GPS_KMPH_PER_KNOT 1.852
38 | #define _GPS_MILES_PER_METER 0.00062137112
39 | #define _GPS_KM_PER_METER 0.001
40 | #define _GPS_FEET_PER_METER 3.2808399
41 | #define _GPS_MAX_FIELD_SIZE 15
42 |
43 | struct RawDegrees
44 | {
45 | uint16_t deg;
46 | uint32_t billionths;
47 | bool negative;
48 | public:
49 | RawDegrees() : deg(0), billionths(0), negative(false)
50 | {}
51 | };
52 |
53 | struct TinyGPSLocation
54 | {
55 | friend class TinyGPSPlus;
56 | public:
57 | bool isValid() const { return valid; }
58 | bool isUpdated() const { return updated; }
59 | uint32_t age() const { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
60 | const RawDegrees &rawLat() { updated = false; return rawLatData; }
61 | const RawDegrees &rawLng() { updated = false; return rawLngData; }
62 | double lat();
63 | double lng();
64 |
65 | TinyGPSLocation() : valid(false), updated(false)
66 | {}
67 |
68 | private:
69 | bool valid, updated;
70 | RawDegrees rawLatData, rawLngData, rawNewLatData, rawNewLngData;
71 | uint32_t lastCommitTime;
72 | void commit();
73 | void setLatitude(const char *term);
74 | void setLongitude(const char *term);
75 | };
76 |
77 | struct TinyGPSDate
78 | {
79 | friend class TinyGPSPlus;
80 | public:
81 | bool isValid() const { return valid; }
82 | bool isUpdated() const { return updated; }
83 | uint32_t age() const { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
84 |
85 | uint32_t value() { updated = false; return date; }
86 | uint16_t year();
87 | uint8_t month();
88 | uint8_t day();
89 |
90 | TinyGPSDate() : valid(false), updated(false), date(0)
91 | {}
92 |
93 | private:
94 | bool valid, updated;
95 | uint32_t date, newDate;
96 | uint32_t lastCommitTime;
97 | void commit();
98 | void setDate(const char *term);
99 | };
100 |
101 | struct TinyGPSTime
102 | {
103 | friend class TinyGPSPlus;
104 | public:
105 | bool isValid() const { return valid; }
106 | bool isUpdated() const { return updated; }
107 | uint32_t age() const { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
108 |
109 | uint32_t value() { updated = false; return time; }
110 | uint8_t hour();
111 | uint8_t minute();
112 | uint8_t second();
113 | uint8_t centisecond();
114 |
115 | TinyGPSTime() : valid(false), updated(false), time(0)
116 | {}
117 |
118 | private:
119 | bool valid, updated;
120 | uint32_t time, newTime;
121 | uint32_t lastCommitTime;
122 | void commit();
123 | void setTime(const char *term);
124 | };
125 |
126 | struct TinyGPSDecimal
127 | {
128 | friend class TinyGPSPlus;
129 | public:
130 | bool isValid() const { return valid; }
131 | bool isUpdated() const { return updated; }
132 | uint32_t age() const { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
133 | int32_t value() { updated = false; return val; }
134 |
135 | TinyGPSDecimal() : valid(false), updated(false), val(0)
136 | {}
137 |
138 | private:
139 | bool valid, updated;
140 | uint32_t lastCommitTime;
141 | int32_t val, newval;
142 | void commit();
143 | void set(const char *term);
144 | };
145 |
146 | struct TinyGPSInteger
147 | {
148 | friend class TinyGPSPlus;
149 | public:
150 | bool isValid() const { return valid; }
151 | bool isUpdated() const { return updated; }
152 | uint32_t age() const { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
153 | uint32_t value() { updated = false; return val; }
154 |
155 | TinyGPSInteger() : valid(false), updated(false), val(0)
156 | {}
157 |
158 | private:
159 | bool valid, updated;
160 | uint32_t lastCommitTime;
161 | uint32_t val, newval;
162 | void commit();
163 | void set(const char *term);
164 | };
165 |
166 | struct TinyGPSSpeed : TinyGPSDecimal
167 | {
168 | double knots() { return value() / 100.0; }
169 | double mph() { return _GPS_MPH_PER_KNOT * value() / 100.0; }
170 | double mps() { return _GPS_MPS_PER_KNOT * value() / 100.0; }
171 | double kmph() { return _GPS_KMPH_PER_KNOT * value() / 100.0; }
172 | };
173 |
174 | struct TinyGPSCourse : public TinyGPSDecimal
175 | {
176 | double deg() { return value() / 100.0; }
177 | };
178 |
179 | struct TinyGPSAltitude : TinyGPSDecimal
180 | {
181 | double meters() { return value() / 100.0; }
182 | double miles() { return _GPS_MILES_PER_METER * value() / 100.0; }
183 | double kilometers() { return _GPS_KM_PER_METER * value() / 100.0; }
184 | double feet() { return _GPS_FEET_PER_METER * value() / 100.0; }
185 | };
186 |
187 | struct TinyGPSHDOP : TinyGPSDecimal
188 | {
189 | double hdop() { return value() / 100.0; }
190 | };
191 |
192 | class TinyGPSPlus;
193 | class TinyGPSCustom
194 | {
195 | public:
196 | TinyGPSCustom() {};
197 | TinyGPSCustom(TinyGPSPlus &gps, const char *sentenceName, int termNumber);
198 | void begin(TinyGPSPlus &gps, const char *_sentenceName, int _termNumber);
199 |
200 | bool isUpdated() const { return updated; }
201 | bool isValid() const { return valid; }
202 | uint32_t age() const { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
203 | const char *value() { updated = false; return buffer; }
204 |
205 | private:
206 | void commit();
207 | void set(const char *term);
208 |
209 | char stagingBuffer[_GPS_MAX_FIELD_SIZE + 1];
210 | char buffer[_GPS_MAX_FIELD_SIZE + 1];
211 | unsigned long lastCommitTime;
212 | bool valid, updated;
213 | const char *sentenceName;
214 | int termNumber;
215 | friend class TinyGPSPlus;
216 | TinyGPSCustom *next;
217 | };
218 |
219 | class TinyGPSPlus
220 | {
221 | public:
222 | TinyGPSPlus();
223 | bool encode(char c); // process one character received from GPS
224 | TinyGPSPlus &operator << (char c) {encode(c); return *this;}
225 |
226 | TinyGPSLocation location;
227 | TinyGPSDate date;
228 | TinyGPSTime time;
229 | TinyGPSSpeed speed;
230 | TinyGPSCourse course;
231 | TinyGPSAltitude altitude;
232 | TinyGPSInteger satellites;
233 | TinyGPSHDOP hdop;
234 |
235 | static const char *libraryVersion() { return _GPS_VERSION; }
236 |
237 | static double distanceBetween(double lat1, double long1, double lat2, double long2);
238 | static double courseTo(double lat1, double long1, double lat2, double long2);
239 | static const char *cardinal(double course);
240 |
241 | static int32_t parseDecimal(const char *term);
242 | static void parseDegrees(const char *term, RawDegrees °);
243 |
244 | uint32_t charsProcessed() const { return encodedCharCount; }
245 | uint32_t sentencesWithFix() const { return sentencesWithFixCount; }
246 | uint32_t failedChecksum() const { return failedChecksumCount; }
247 | uint32_t passedChecksum() const { return passedChecksumCount; }
248 |
249 | private:
250 | enum {GPS_SENTENCE_GPGGA, GPS_SENTENCE_GPRMC, GPS_SENTENCE_OTHER};
251 |
252 | // parsing state variables
253 | uint8_t parity;
254 | bool isChecksumTerm;
255 | char term[_GPS_MAX_FIELD_SIZE];
256 | uint8_t curSentenceType;
257 | uint8_t curTermNumber;
258 | uint8_t curTermOffset;
259 | bool sentenceHasFix;
260 |
261 | // custom element support
262 | friend class TinyGPSCustom;
263 | TinyGPSCustom *customElts;
264 | TinyGPSCustom *customCandidates;
265 | void insertCustom(TinyGPSCustom *pElt, const char *sentenceName, int index);
266 |
267 | // statistics
268 | uint32_t encodedCharCount;
269 | uint32_t sentencesWithFixCount;
270 | uint32_t failedChecksumCount;
271 | uint32_t passedChecksumCount;
272 |
273 | // internal utilities
274 | int fromHex(char a);
275 | bool endOfTermHandler();
276 | };
277 |
278 | #endif // def(__TinyGPSPlus_h)
279 |
--------------------------------------------------------------------------------