In this project I created a device to display Ordnance Survey grid references using an ESP32 and a GPS chip in a 3D printed case.

The Maths

A little background on the earth: The earth is roughly an ellipsoid (squashed sphere), but as these are approximations no one model will perfectly encapsulate the data, several different ellipsoids exist, but we will only be looking at 2 in this post, WGS84 and Airy 1830

GPS uses the WGS84 ellipsoid, a system which works across the entire world, whereas Ordnance Survey’s grid references use the Airy1830 ellipsoid, as it works slightly better for the UK. Thus, I need to convert from one to the other before I can calculate the grid reference.

  1. Get GPS data from chip (Performed by the TinyGPS++ Library on the microcontroller)
  2. Convert to point in 3D space using trig \(\{Lon,\;Lat,\;Alt\}_{WGS84}\rightarrow ECEF_{WGS84}\)
  3. Perform a Helmert transformation \(\overrightarrow{OX}_{WGS84} \rightarrow \overrightarrow{OX}_{Airy}\)
  4. \(ECEF_{Airy} \rightarrow \{Lon,\;Lat,\;Alt\}_{Airy}\) (various methods are available)
  5. Perform Transverse Mercator Projection \(\{Lon,\;Lat,\;Alt\}_{Airy} \rightarrow \{Northing,\;Easting\}_{OSGB36}\)
  6. Format the Data into a grid reference \(\{Northing,\;Easting\}_{OSGB36} \rightarrow Grid\,Reference_{OSGB36}\)

This code is implemented within the v1 version of the library here

1) Convert to point in 3D space using trig

Earth Centered, Earth fixed coordinates is a way of expressing a point (on the earth) as a vector in 3D space, where the earth is both at the origin (centred) and in fixed position.

Diagram of the Earth

In this 2D diagram you can see that: \[x = (n+alt)\cos\phi\] \[z = (n+alt)\sin\phi\]

This extends to 3D quite simply with \[\overrightarrow{OX} = (n+alt)\cdot\begin{pmatrix} \cos\phi\cos\lambda\\ \cos\phi\sin\lambda\\ \sin\phi \end{pmatrix}\]

2) Perform a Helmert transformation

The Helmert transform takes a ECEF vector for one ellipsoid and transforms it for another, it is just a matrix transformation and translation.

\[\overrightarrow{OX}_{Airy} = \mathbf{M}\times\overrightarrow{OX}_{WGS84} + \vec{t}\]

3) Convert back to Longitude and Latitude

There are several methods to convert this back to a longitude/latitude pair:

I chose to use Olson’s Algorithm as from my experience it was more accurate than the other two, and does not have a loop like a Newton-Raphson would.

4) Perform Transverse Mercator Projection

This is performing a Mercator Projection along a line of Longitude. This means that while the Mercator projection diverges towards the poles, you can take a Transverse Mercator projection every few (UTM is every 6) degrees and be able to get an accurate map for that region, even towards the poles. The maths is very complicated but is outlined in the Ordnance Survey Document.

5) Format the Data into a grid reference

The projected map is split into 25 500km x 500km squares, with each being split into 25 100km x 100km squares. Then a 6 figure grid reference is the value within the square to a precision of 100m for both northing and easting as seen below:

Diagram of the Royal Greenwich Observatory


3D Printing

I designed a case in OnShape3D to work with the GT-U7 chip and the antenna that it comes with available here (as I’ll go through later, I had to modify it to fit a replacement antenna).

Sketch of the case

And here is the finished* V1 device!

The Finished Device

* I still am waiting for a replacement antenna that will fit inside the case, but besides from that it’s completed

Bill of Materials (V1)

  • ESP32 WROOM development board (~£5 on eBay)
  • GT-U7 GPS chip (~£10 on eBay)
  • replacement antenna (because I broke the first one)
  • 20x4 Character LCD (~£7 on eBay)
  • 2x3000mAh 18650 batteries ( ~£9 on eBay)
  • 18650 battery holder (~£3 on eBay)
  • TP4056 LiPo charging circuit
  • Consumables
    • Solder
    • Wires
    • 3d printer filament


Electronic Schematic


As anyone who knows me well enough can already tell, this turned into a 5 act drama

Getting a fix

I started with a NEO-6M but after a while they found difficulty getting a fix. I then swapped to a GT-U7 based on the advice of a friend, which worked fine for a while, after failing. After getting a replacement antenna (which had issues with a U.FL connector being a bit loose in itself; fixed with a bit of electrical tape) and was able to get a fix outside. For a V2, I plan to use an BN-880 chip with which I can reliably get 8-12 satellites from inside (only 4 or 5 are needed for a positional fix).

Weak USB ports on the microcontroller

When doing some preliminary tests with the GPS chips, I managed to break off the microUSB port off a few of these. Whilst it is possible to use a UART/USB converter, It is still a pain.

Unable to program while the GPS is wired in

I have to disconnect the TX pin from the GPS chip before I attempt programming the chip, as the chip can be programmed by either UART port, so I had to fit a header with a removable bridging connector for any updates.

Unreliable Altitude

The altitude floats. This graph was taken across 5-10 minutes with the chip being on the ground in my garden. I will be investigating this further at a later date.

Floating Altitude

Where Next for this project?

So I went out and bought some more maps with some different projection methods used, to see if I could implement things with them, but that will wait until the second version.

Further Reading

Image Credits