u-blox / ubxlib

Portable C libraries which provide APIs to build applications with u-blox products and services. Delivered as add-on to existing microcontroller and RTOS SDKs.
Apache License 2.0
313 stars 95 forks source link

Connecting NEO-6M to ESP32 #262

Closed jnschnkr closed 4 months ago

jnschnkr commented 4 months ago

I have a NEO-6M module and want to connect it with an ESP32S3 board. I managed to get the position with the nmea_parser example inside the ESP-IDF but wanted to use the ubxlib now. My code is mostly copied from the gnss example. I've tried everything I can find but I'm unable to make it work and couldn't find more information on the errors I get.

/*
 * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: CC0-1.0
 */

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "driver/uart.h"
#include "ubxlib.h"

#define GNSS_RX_PIN 5
#define GNSS_TX_PIN 6

// Optionally, define a user context which you can use to pass
// information to a callback that does not have a dedicated
// void * callback parameter (this is the case with
// uGnssPosGetStreamedStart()).
typedef struct {
    char *pSomething;
    int32_t somethingElse;
} MyContext_t;

// Count of the number of position fixes received
static size_t gPositionCount = 0;

static const uDeviceCfg_t gDeviceCfg = {
    .deviceType = U_DEVICE_TYPE_GNSS,
    .deviceCfg = {
        .cfgGnss = {
            .moduleType = U_GNSS_MODULE_TYPE_M9,
            .pinEnablePower = -1,
            .pinDataReady = -1, // Not used
            // There is an additional field here:
            // "i2cAddress", which we do NOT set,
            // we allow the compiler to set it to 0
            // and all will be fine. You may set the
            // field to the I2C address of your GNSS
            // device if you have modified the I2C
            // address of your GNSS device to something
            // other than the default value of 0x42,
            // for example:
            // .i2cAddress = 0x43
        },
    },
    .transportType = U_DEVICE_TRANSPORT_TYPE_UART,
    .transportCfg = {
        .cfgUart = {
            .uart = UART_NUM_1,
            .baudRate = U_GNSS_UART_BAUD_RATE, /* Use 0 to try all possible baud rates
                                                  and find the correct one. */
            .pinTxd = GNSS_TX_PIN,  // Use -1 if on Zephyr or Linux or Windows
            .pinRxd = GNSS_RX_PIN,  // Use -1 if on Zephyr or Linux or Windows
            .pinCts = -1,  // Use -1 if on Zephyr
            .pinRts = -1,  // Use -1 if on Zephyr
            .pPrefix = NULL
        },
    },
};

static char latLongToBits(int32_t thingX1e7,
                          int32_t *pWhole,
                          int32_t *pFraction)
{
    char prefix = '+';

    // Deal with the sign
    if (thingX1e7 < 0) {
        thingX1e7 = -thingX1e7;
        prefix = '-';
    }
    *pWhole = thingX1e7 / 10000000;
    *pFraction = thingX1e7 % 10000000;

    return prefix;
}

// Callback for position reception.
static void callback(uDeviceHandle_t gnssHandle,
                     int32_t errorCode,
                     int32_t latitudeX1e7,
                     int32_t longitudeX1e7,
                     int32_t altitudeMillimetres,
                     int32_t radiusMillimetres,
                     int32_t speedMillimetresPerSecond,
                     int32_t svs,
                     int64_t timeUtc)
{
    char prefix[2] = {0};
    int32_t whole[2] = {0};
    int32_t fraction[2] = {0};

    // Pick up our user context
    MyContext_t *pContext = (MyContext_t *) pUDeviceGetUserContext(gnssHandle);

    // Not using these, just keep the compiler happy
    (void) gnssHandle;
    (void) altitudeMillimetres;
    (void) radiusMillimetres;
    (void) speedMillimetresPerSecond;
    (void) svs;
    (void) timeUtc;
    // We don't actually use the user context here, but
    // of course _you_ could
    (void) pContext;

    if (errorCode == 0) {
        prefix[0] = latLongToBits(longitudeX1e7, &(whole[0]), &(fraction[0]));
        prefix[1] = latLongToBits(latitudeX1e7, &(whole[1]), &(fraction[1]));
        uPortLog("I am here: https://maps.google.com/?q=%c%d.%07d,%c%d.%07d\n",
                 prefix[1], whole[1], fraction[1], prefix[0], whole[0], fraction[0]);
        gPositionCount++;
    }
}

void app_main(void)
{
    uDeviceHandle_t devHandle = NULL;
    int32_t returnCode;
    int32_t guardCount = 0;
    MyContext_t context = {0};

    uPortInit();
    uDeviceInit();

    // Open the device
    returnCode = uDeviceOpen(&gDeviceCfg, &devHandle);
    uPortLog("Opened device with return code %d.\n", returnCode);

    if (returnCode == 0) {
        // Since we are not using the common APIs we do not need
        // to call uNetworkInteraceUp()/uNetworkInteraceDown().

        // If you need to pass context data to
        // uGnssPosGetStreamedStart(), which does not include
        // a user parameter in its function signature, set
        // a user context for ourselves in the device, which
        // we can pick up in callback()
        uDeviceSetUserContext(devHandle, (void *) &context);

        // Start to get position
        uPortLog("Starting position stream.\n");
        returnCode = uGnssPosGetStreamedStart(devHandle,
                                              U_GNSS_POS_STREAMED_PERIOD_DEFAULT_MS,
                                              callback);
        uPortLog("Start stream with return code %d.\n", returnCode);

        if (returnCode == 0) {

            uPortLog("Waiting up to 60 seconds for 5 position fixes.\n");
            while ((gPositionCount < 5) && (guardCount < 60)) {
                uPortTaskBlock(1000);
                guardCount++;
            }
            // Stop getting position
            uGnssPosGetStreamedStop(devHandle);

        } else {
            uPortLog("Unable to start position stream!\n");
        }

        // Close the device
        // Note: we don't power the device down here in order
        // to speed up testing; you may prefer to power it off
        // by setting the second parameter to true.
        uDeviceClose(devHandle, false);

    } else {
        uPortLog("Unable to open GNSS!\n");
    }

    // Tidy up
    uDeviceDeinit();
    uPortDeinit();

    uPortLog("Done.\n");
}

Using U_GNSS_MODULE_TYPE_ANY I get returnCode -24 with the following output:

U_GNSS: initialising with ENABLE_POWER pin not connected, transport type UART.
U_GNSS: sent command b5 62 0a 04 00 00 0e 34.
U_GNSS: decoded UBX response 0x0a 0x04: 37 2e 30 33 20 28 34 35 39 36 39 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 30 30 34 30 30 30 37 00 00 [body 40 byte(s)].
U_GNSS_PWR: could not identify the module type.
Opened device with return code -24.
Unable to open GNSS!
Done.

When opening the device and with U_GNSS_MODULE_TYPE_M8 I get returnCode -8.

U_GNSS: initialising with ENABLE_POWER pin not connected, transport type UART.
U_GNSS: sent command b5 62 0a 06 00 00 10 3a.
U_GNSS: decoded UBX response 0x0a 0x06: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [body 120 byte(s)].
U_GNSS: sent command b5 62 06 04 04 00 00 00 09 00 17 76.
U_GNSS: sent command b5 62 0a 06 00 00 10 3a.
U_GNSS: decoded UBX response 0x0a 0x06: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [body 120 byte(s)].
U_GNSS: sent command b5 62 0a 28 00 00 32 a0.
Opened device with return code -8.
Unable to open GNSS!
Done.

Configurations U_GNSS_MODULE_TYPE_M9 and U_GNSS_MODULE_TYPE_M10 allow me to open the device with returnCode 0 but I get returnCode -1025 when starting the stream. The full output is as follows:

U_GNSS: initialising with ENABLE_POWER pin not connected, transport type UART.
U_GNSS: sent command b5 62 0a 06 00 00 10 3a.
U_GNSS: decoded UBX response 0x0a 0x06: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3f 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [body 120 byte(s)].
U_GNSS: sent command b5 62 06 04 04 00 00 00 09 00 17 76.
U_GNSS: sent command b5 62 0a 06 00 00 10 3a.
U_GNSS: decoded UBX response 0x0a 0x06: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [body 120 byte(s)].
Opened device with return code 0.
Starting position stream.
U_GNSS: sent command b5 62 06 8b 08 00 00 00 00 00 ff ff 21 00 b8 cc.
U_GNSS: got Nack for 0x06 0x8b.
U_GNSS: sent command b5 62 06 8a 10 00 01 03 00 00 01 00 21 30 e8 03 02 00 21 30 01 00 35 90.
U_GNSS: decoded UBX response 0x05 0x00: 06 8a [body 2 byte(s)].
Start stream with return code -1025.
Unable to start position stream!
Done.

Thanks for any inputs on how I could solve my problem.

cturvey commented 4 months ago

The Generation 6 devices (2019) have been End-of-Life for many years, it's probably unrealistic to expect support now and moving forward. UBXLIB might be overkill if you're just skimming NMEA/UBX for a GPS Only receiver.

UBX-NAV-PVT and UBX-NAV-SAT not supported by the firmwares, as I recall. No GALILEO support GLONASS as alternative with NEO-6N, single RF down converter on front-end

RobMeades commented 4 months ago

Hi, and thanks for posting. I'm afraid Clive is correct: you'll see from u_errror_common.h that code -24 means U_ERROR_COMMON_UNKNOWN_MODULE_TYPE; ubxlib support for GNSS modules begins with the M8 series, the M6 GNSS module doesn't support/understand most of the UBX messages that ubxlib will send.

Sorry!

jnschnkr commented 4 months ago

Thanks for your help anyways. At least, I know now that it's not supported and that I don't need to try any longer.