diff --git a/.vscode/settings.json b/.vscode/settings.json
index e1a98af224ab9e9c71af4a5ba32200cd6d082039..5791694b122349dd5977372e80e5978a984cdf42 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -134,12 +134,14 @@
         "croll",
         "cwise",
         "cyaw",
+        "datasheet",
         "deleteme",
         "DMEIE",
         "Doxyfile",
         "doxygen",
         "DRDY",
         "Duca",
+        "ECEF",
         "Ecompass",
         "Eigen",
         "elfs",
@@ -175,6 +177,7 @@
         "logdecoder",
         "Luca",
         "MEKF",
+        "microcontrollers",
         "MINC",
         "miosix",
         "mkdir",
@@ -184,6 +187,7 @@
         "NBAR",
         "NDTR",
         "NGPS",
+        "Nidasio",
         "NMAG",
         "NMEA",
         "NMEKF",
@@ -193,6 +197,7 @@
         "PINC",
         "Pitot",
         "Plin",
+        "POSLLH",
         "Qgbw",
         "Qget",
         "Qhandle",
@@ -218,6 +223,7 @@
         "testsuite",
         "TSCPP",
         "Ublox",
+        "ubloxgps",
         "UBXACK",
         "UBXGPS",
         "UBXNAV",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c8fdb7953d78dbc335ce4b0cddd2a3a6681fe1e2..002a51ede24064c42d385c9ca7622101b0241e9f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -353,7 +353,7 @@ add_executable(test-ms5803 src/tests/sensors/test-ms5803.cpp)
 sbs_target(test-ms5803 stm32f429zi_skyward_death_stack_x)
 
 add_executable(test-ubxgps-serial src/tests/sensors/test-ubxgps-serial.cpp)
-sbs_target(test-ubxgps-serial stm32f429zi_skyward_death_stack_x)
+sbs_target(test-ubxgps-serial stm32f429zi_stm32f4discovery)
 
 add_executable(test-ubxgps-spi src/tests/sensors/test-ubxgps-spi.cpp)
 sbs_target(test-ubxgps-spi stm32f429zi_skyward_death_stack_x)
diff --git a/src/shared/drivers/adc/InternalADC.cpp b/src/shared/drivers/adc/InternalADC.cpp
index acfe5e21f31f2b8e394d516c4688086f8d351ddc..32576a66240a1d87266533b5cb07abb0136870e1 100644
--- a/src/shared/drivers/adc/InternalADC.cpp
+++ b/src/shared/drivers/adc/InternalADC.cpp
@@ -219,14 +219,14 @@ InternalADCData InternalADC::sampleImpl()
 
         // This should trigger the DMA stream for each channel's conversion
 
-        // Wait for tranfer end
+        // Wait for transfer end
         while (!(*statusReg & (transferCompleteMask | transferErrorMask)))
             ;
 
         // Clear the transfer complete flag
         *clearFlagReg |= transferCompleteMask;
 
-        // If and error has occurred (probaly due to a higher priority stream)
+        // If and error has occurred (probably due to a higher priority stream)
         // don't update the timestamp, the values should not have been updated
         if (*statusReg & transferErrorMask)
         {
diff --git a/src/shared/sensors/UBXGPS/UBXFrame.h b/src/shared/sensors/UBXGPS/UBXFrame.h
index 9f1593baaa01a1ce8b3d7be31488e9ba12cfd05d..50b8ca12af6bc9526a4445623410ffe17f7e1546 100644
--- a/src/shared/sensors/UBXGPS/UBXFrame.h
+++ b/src/shared/sensors/UBXGPS/UBXFrame.h
@@ -35,14 +35,16 @@ namespace Boardcore
  */
 enum class UBXMessage : uint16_t
 {
-    UBX_NAV_PVT  = 0x0701,  // Navigation position velocity time solution
-    UBX_ACK_NAK  = 0x0005,  // Message acknowledged
-    UBX_ACK_ACK  = 0x0105,  // Message not acknowledged
-    UBX_CFG_PRT  = 0x0006,  // Port configuration
-    UBX_CFG_MSG  = 0x0106,  // Set message rate
-    UBX_CFG_RST  = 0x0406,  // Reset receiver
-    UBX_CFG_RATE = 0x0806,  // Navigation/measurement rate settings
-    UBX_CFG_NAV5 = 0x2406,  // Navigation engine settings
+    UBX_NAV_POSLLH = 0x0201,  // Geodetic position solution
+    UBX_NAV_SOL    = 0x0601,  // Navigation solution information
+    UBX_NAV_PVT    = 0x0701,  // Navigation position velocity time solution
+    UBX_ACK_NAK    = 0x0005,  // Message acknowledged
+    UBX_ACK_ACK    = 0x0105,  // Message not acknowledged
+    UBX_CFG_PRT    = 0x0006,  // Port configuration
+    UBX_CFG_MSG    = 0x0106,  // Set message rate
+    UBX_CFG_RST    = 0x0406,  // Reset receiver
+    UBX_CFG_RATE   = 0x0806,  // Navigation/measurement rate settings
+    UBX_CFG_NAV5   = 0x2406,  // Navigation engine settings
 };
 
 /**
@@ -200,6 +202,52 @@ public:
     bool isValid() const;
 };
 
+struct UBXPosllhFrame : public UBXFrame
+{
+    struct __attribute__((packed)) Payload
+    {
+        uint32_t iTOW;   // GPS time of week of the navigation epoch [ms]
+        int32_t lon;     // Longitude {1e-7} [deg]
+        int32_t lat;     // Latitude {1e-7} [deg]
+        int32_t height;  // Height above ellipsoid [mm]
+        int32_t hMSL;    // Height above mean sea level [mm]
+        uint32_t hAcc;   // Horizontal accuracy estimate [mm]
+        uint32_t vAcc;   // Vertical accuracy estimate [mm]
+    };
+
+    Payload& getPayload() const;
+
+    bool isValid() const;
+};
+
+struct UBXSolFrame : public UBXFrame
+{
+    struct __attribute__((packed)) Payload
+    {
+        uint32_t iTOW;   // GPS time of week of the navigation epoch [ms]
+        int32_t fTOW;    // Fractional nanoseconds remainder of rounded ms
+        int16_t week;    // GPS week (GPS time)
+        uint8_t gpsFix;  // GPS Fix type
+        uint8_t flags;   // Fix status flags
+        int32_t ecefX;   // ECEF X coordinate [cm]
+        int32_t ecefY;   // ECEF Y coordinate [cm]
+        int32_t ecefZ;   // ECEF Z coordinate [cm]
+        uint32_t pAcc;   // 3D position accuracy estimate [cm]
+        int32_t ecefVX;  // ECEF X velocity [cm/s]
+        int32_t ecefVY;  // ECEF y velocity [cm/s]
+        int32_t ecefVZ;  // ECEF z velocity [cm/s]
+        uint32_t sAcc;   // [cm/s]
+        uint16_t pDOP;   // Position DOP
+        uint8_t reserved1;
+        uint8_t numSV;  // Number of satellites used in Nav Solution
+        uint8_t reserved2;
+    };
+
+    Payload& getPayload() const;
+
+    bool isValid() const;
+};
+
 inline UBXFrame::UBXFrame(UBXMessage message, const uint8_t* payload,
                           uint16_t payloadLength)
     : message(static_cast<uint16_t>(message)), payloadLength(payloadLength)
@@ -300,9 +348,29 @@ inline UBXPvtFrame::Payload& UBXPvtFrame::getPayload() const
     return (Payload&)payload;
 }
 
+inline UBXPosllhFrame::Payload& UBXPosllhFrame::getPayload() const
+{
+    return (Payload&)payload;
+}
+
+inline UBXSolFrame::Payload& UBXSolFrame::getPayload() const
+{
+    return (Payload&)payload;
+}
+
 inline bool UBXPvtFrame::isValid() const
 {
     return UBXFrame::isValid() && getMessage() == UBXMessage::UBX_NAV_PVT;
 }
 
+inline bool UBXPosllhFrame::isValid() const
+{
+    return UBXFrame::isValid() && getMessage() == UBXMessage::UBX_NAV_POSLLH;
+}
+
+inline bool UBXSolFrame::isValid() const
+{
+    return UBXFrame::isValid() && getMessage() == UBXMessage::UBX_NAV_SOL;
+}
+
 }  // namespace Boardcore
diff --git a/src/shared/sensors/UBXGPS/UBXGPSSerial.cpp b/src/shared/sensors/UBXGPS/UBXGPSSerial.cpp
index 4bd60787c5a033840be60e2b64a2bb4c4e218bda..d6a3a9bec5bd35bc4093f24dc65f646a55a474b4 100644
--- a/src/shared/sensors/UBXGPS/UBXGPSSerial.cpp
+++ b/src/shared/sensors/UBXGPS/UBXGPSSerial.cpp
@@ -55,14 +55,14 @@ bool UBXGPSSerial::init()
         return false;
     }
 
-    LOG_DEBUG(logger, "Resetting the device...");
+    // LOG_DEBUG(logger, "Resetting the device...");
 
-    if (!reset())
-    {
-        lastError = SensorErrors::INIT_FAIL;
-        LOG_ERR(logger, "Could not reset the device");
-        return false;
-    }
+    // if (!reset())
+    // {
+    //     lastError = SensorErrors::INIT_FAIL;
+    //     LOG_ERR(logger, "Could not reset the device");
+    //     return false;
+    // }
 
     LOG_DEBUG(logger, "Setting the UBX protocol...");
 
@@ -91,9 +91,16 @@ bool UBXGPSSerial::init()
         return false;
     }
 
-    LOG_DEBUG(logger, "Setting the PVT message rate...");
+    LOG_DEBUG(logger, "Setting the messages rate...");
 
-    if (!setPVTMessageRate())
+    if (!setPOSLLHMessageRate())
+    {
+        lastError = SensorErrors::INIT_FAIL;
+        LOG_ERR(logger, "Could not set the PVT message rate");
+        return false;
+    }
+
+    if (!setSOLMessageRate())
     {
         lastError = SensorErrors::INIT_FAIL;
         LOG_ERR(logger, "Could not set the PVT message rate");
@@ -289,6 +296,30 @@ bool UBXGPSSerial::setPVTMessageRate()
     return safeWriteUBXFrame(frame);
 }
 
+bool UBXGPSSerial::setPOSLLHMessageRate()
+{
+    uint8_t payload[] = {
+        0x01, 0x02,  // POSLLH message
+        0x01         // Rate = 1
+    };
+
+    UBXFrame frame{UBXMessage::UBX_CFG_MSG, payload, sizeof(payload)};
+
+    return safeWriteUBXFrame(frame);
+}
+
+bool UBXGPSSerial::setSOLMessageRate()
+{
+    uint8_t payload[] = {
+        0x01, 0x06,  // POSLLH message
+        0x01         // Rate = 1
+    };
+
+    UBXFrame frame{UBXMessage::UBX_CFG_MSG, payload, sizeof(payload)};
+
+    return safeWriteUBXFrame(frame);
+}
+
 bool UBXGPSSerial::readUBXFrame(UBXFrame& frame)
 {
     // Search UBX frame preamble byte by byte
@@ -311,7 +342,7 @@ bool UBXGPSSerial::readUBXFrame(UBXFrame& frame)
         else
         {
             i = 0;
-            LOG_DEBUG(logger, "Received unexpected byte: {:02x} {:#c}", c, c);
+            // LOG_DEBUG(logger, "Received unexpected byte: {:02x}", c);
         }
     }
 
@@ -394,30 +425,67 @@ void UBXGPSSerial::run()
 {
     while (!shouldStop())
     {
-        UBXPvtFrame pvt;
+        UBXFrame frame;
 
         // Try to read the message
-        if (!readUBXFrame(pvt))
+        if (!readUBXFrame(frame))
         {
             LOG_DEBUG(logger, "Unable to read a UBX message");
             continue;
         }
 
-        UBXPvtFrame::Payload& pvtP = pvt.getPayload();
-
-        threadSample.gpsTimestamp =
-            TimestampTimer::getInstance().getTimestamp();
-        threadSample.latitude      = (float)pvtP.lat / 1e7;
-        threadSample.longitude     = (float)pvtP.lon / 1e7;
-        threadSample.height        = (float)pvtP.height / 1e3;
-        threadSample.velocityNorth = (float)pvtP.velN / 1e3;
-        threadSample.velocityEast  = (float)pvtP.velE / 1e3;
-        threadSample.velocityDown  = (float)pvtP.velD / 1e3;
-        threadSample.speed         = (float)pvtP.gSpeed / 1e3;
-        threadSample.track         = (float)pvtP.headMot / 1e5;
-        threadSample.positionDOP   = (float)pvtP.pDOP / 1e2;
-        threadSample.satellites    = pvtP.numSV;
-        threadSample.fix           = pvtP.fixType;
+        uint8_t data[frame.getLength()];
+        frame.writePacked(data);
+
+        UBXPvtFrame pvt;
+        pvt.readPacked(data);
+
+        if (pvt.isValid())
+        {
+            UBXPvtFrame::Payload& pvtP = pvt.getPayload();
+
+            threadSample.gpsTimestamp =
+                TimestampTimer::getInstance().getTimestamp();
+            threadSample.latitude      = (float)pvtP.lat / 1e7;
+            threadSample.longitude     = (float)pvtP.lon / 1e7;
+            threadSample.height        = (float)pvtP.height / 1e3;
+            threadSample.velocityNorth = (float)pvtP.velN / 1e3;
+            threadSample.velocityEast  = (float)pvtP.velE / 1e3;
+            threadSample.velocityDown  = (float)pvtP.velD / 1e3;
+            threadSample.speed         = (float)pvtP.gSpeed / 1e3;
+            threadSample.track         = (float)pvtP.headMot / 1e5;
+            threadSample.positionDOP   = (float)pvtP.pDOP / 1e2;
+            threadSample.satellites    = pvtP.numSV;
+            threadSample.fix           = pvtP.fixType;
+        }
+
+        UBXPosllhFrame posllh;
+        posllh.readPacked(data);
+
+        if (posllh.isValid())
+        {
+            UBXPosllhFrame::Payload& posllhP = posllh.getPayload();
+
+            threadSample.gpsTimestamp =
+                TimestampTimer::getInstance().getTimestamp();
+            threadSample.latitude  = (float)posllhP.lat / 1e7;
+            threadSample.longitude = (float)posllhP.lon / 1e7;
+            threadSample.height    = (float)posllhP.height / 1e3;
+        }
+
+        UBXSolFrame sol;
+        sol.readPacked(data);
+
+        if (sol.isValid())
+        {
+            UBXSolFrame::Payload& solP = sol.getPayload();
+
+            threadSample.gpsTimestamp =
+                TimestampTimer::getInstance().getTimestamp();
+            threadSample.positionDOP = (float)solP.pDOP / 1e2;
+            threadSample.satellites  = solP.numSV;
+            threadSample.fix         = solP.gpsFix;
+        }
 
         StackLogger::getInstance().updateStack(THID_GPS);
     }
diff --git a/src/shared/sensors/UBXGPS/UBXGPSSerial.h b/src/shared/sensors/UBXGPS/UBXGPSSerial.h
index 4785778c2beab52185b2b614f06db7ab2c0e4769..d0a91a1c84f4477b0cec1651e85a0030ca3aafe0 100644
--- a/src/shared/sensors/UBXGPS/UBXGPSSerial.h
+++ b/src/shared/sensors/UBXGPS/UBXGPSSerial.h
@@ -132,6 +132,10 @@ private:
      */
     bool setPVTMessageRate();
 
+    bool setPOSLLHMessageRate();
+
+    bool setSOLMessageRate();
+
     /**
      * @brief Reads a UBX frame.
      *
diff --git a/src/tests/sensors/test-ubxgps-serial.cpp b/src/tests/sensors/test-ubxgps-serial.cpp
index cf7fe1c50ed6a63c56ec534207b02bbee16a6898..8c61fb72b5523c9d761a1aeafb8e042db9140757 100644
--- a/src/tests/sensors/test-ubxgps-serial.cpp
+++ b/src/tests/sensors/test-ubxgps-serial.cpp
@@ -30,38 +30,31 @@
 using namespace Boardcore;
 using namespace miosix;
 
-#define RATE 4
+typedef miosix::Gpio<GPIOD_BASE, 5> u2tx2;
+
+#define RATE 1
 
 int main()
 {
-    (void)TimestampTimer::getInstance();
-
-    printf("Welcome to the ublox test\n");
+    u2tx2::mode(Mode::ALTERNATE);
+    u2tx2::alternateFunction(7);
 
     // Keep GPS baud rate at default for easier testing
     UBXGPSSerial gps(38400, RATE, 2, "gps", 9600);
-    UBXGPSData dataGPS;
+    UBXGPSData data;
     printf("Gps allocated\n");
 
     // Init the gps
     if (gps.init())
-    {
         printf("Successful gps initialization\n");
-    }
     else
-    {
         printf("Failed gps initialization\n");
-    }
 
-    // Perform the selftest
+    // Perform the self test
     if (gps.selfTest())
-    {
-        printf("Successful gps selftest\n");
-    }
+        printf("Successful gps self test\n");
     else
-    {
-        printf("Failed gps selftest\n");
-    }
+        printf("Failed gps self test\n");
 
     // Start the gps thread
     gps.start();
@@ -69,23 +62,21 @@ int main()
 
     while (true)
     {
-        printf("a\n");
         // Give time to the thread
         Thread::sleep(1000 / RATE);
 
         // Sample
         gps.sample();
-        printf("b\n");
-        dataGPS = gps.getLastSample();
+        data = gps.getLastSample();
 
         // Print out the latest sample
         printf(
-            "[gps] timestamp: % 4.3f, fix: %01d lat: % f lon: % f "
-            "height: %4.1f nsat: %2d speed: %3.2f velN: % 3.2f velE: % 3.2f "
-            "track %3.1f\n",
-            (float)dataGPS.gpsTimestamp / 1000000, dataGPS.fix,
-            dataGPS.latitude, dataGPS.longitude, dataGPS.height,
-            dataGPS.satellites, dataGPS.speed, dataGPS.velocityNorth,
-            dataGPS.velocityEast, dataGPS.track);
+            "[%.2f] lat: % f lon: % f height: %4.1f velN: % 3.2f velE: % 3.2f "
+            "velD: % 3.2f speed: %3.2f track: %.2f posDOP: %.2f nSat: %2d fix: "
+            "%01d\n",
+            data.gpsTimestamp / 1e6, data.latitude, data.longitude, data.height,
+            data.velocityNorth, data.velocityEast, data.velocityDown,
+            data.speed, data.track, data.positionDOP, data.satellites,
+            data.fix);
     }
 }