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
310 stars 94 forks source link

Mac Address is -1 after ble example script #266

Open PaulaScharf opened 3 months ago

PaulaScharf commented 3 months ago

Hi, I attempted to run the ble example script on my ESP32-S2 based microcontroller with a NINA-B312. I adjusted the config according to my pins and moduleType. The code looks like this:

/*
 * Simple BLE SPS example using ubxlib
 *
 * This example implements a SPS echo server to which a client can
 * connect and send data and then get that data echoed back.
 * A typical client can be the "U-blox Bluetooth Low Energy"
 * application available for Android and IOS.
 *
 */

#include <stdio.h>
#include <Arduino.h>

#include "ubxlib.h"

// Change all -1 values below to appropriate pin and settings values
// appropriate for your module connection.
static const uDeviceCfg_t gDeviceCfg = {
    .deviceType = U_DEVICE_TYPE_SHORT_RANGE,
    .deviceCfg = {
        .cfgSho = {
            .moduleType = 4
        },
    },
    .transportType = U_DEVICE_TRANSPORT_TYPE_UART,
    .transportCfg = {
        .cfgUart = {
            .uart = 1,
            .baudRate = 115200,
            .pinTxd = 17,
            .pinRxd = 18,
            .pinCts = -1,//34,
            .pinRts = -1,//33,
            .pPrefix = NULL // Relevant for Linux only
        },
    },
};

static const uNetworkCfgBle_t gNetworkCfg = {
    .type = U_NETWORK_TYPE_BLE,
    .role = U_BLE_CFG_ROLE_PERIPHERAL,
    .spsServer = true
};

static void connectionCallback(int32_t connHandle, char *address, int32_t status,
                               int32_t channel, int32_t mtu, void *pParameters)
{
    if (status == (int32_t)U_BLE_SPS_CONNECTED) {
        Serial.printf("Connected to: %s\n", address);
    } else if (status == (int32_t)U_BLE_SPS_DISCONNECTED) {
        if (connHandle != U_BLE_SPS_INVALID_HANDLE) {
            Serial.printf("Diconnected\n");
        } else {
            Serial.printf("* Connection attempt failed\n");
        }
    }
}

static void dataAvailableCallback(int32_t channel, void *pParameters)
{
    char buffer[100];
    int32_t length;
    uDeviceHandle_t *pDeviceHandle = (uDeviceHandle_t *)pParameters;
    do {
        length = uBleSpsReceive(*pDeviceHandle, channel, buffer, sizeof(buffer) - 1);
        if (length > 0) {
            buffer[length] = 0;
            Serial.printf("Received: %s\n", buffer);
            // Echo the received data
            uBleSpsSend(*pDeviceHandle, channel, buffer, length);
        }
    } while (length > 0);
}

void setup()
{
    Serial.begin(9600);
    delay(1500);
    // Remove the line below if you want the log printouts from ubxlib
    uPortLogOff();
    // Initiate ubxlib
    uPortInit();
    uDeviceInit();
    // And the U-blox module
    int32_t errorCode;
    uDeviceHandle_t deviceHandle;
    uPortTaskBlock(1000);
    Serial.printf("\nInitiating the module...\n");
    // Serial1.begin(115200,SERIAL_8N1, RX, TX);
    errorCode = uDeviceOpen(&gDeviceCfg, &deviceHandle);
    if (errorCode == 0) {
        Serial.printf("Bringing up the ble network...\n");
        errorCode = uNetworkInterfaceUp(deviceHandle, gNetworkCfg.type, &gNetworkCfg);
        if (errorCode == 0) {
            uBleSpsSetCallbackConnectionStatus(deviceHandle,
                                               connectionCallback,
                                               &deviceHandle);
            uBleSpsSetDataAvailableCallback(deviceHandle,
                                            dataAvailableCallback,
                                            &deviceHandle);
            Serial.printf("\n== Start a SPS client e.g. in a phone ==\n\n");
            Serial.printf("Waiting for connections...\n");
            while (1) {
                uPortTaskBlock(1000);
            }
        } else {
            Serial.printf("* Failed to bring up the network: %d\n", errorCode);
        }
        uDeviceClose(deviceHandle, false);
    } else {
        Serial.printf("* Failed to initiate the module: %d\n", errorCode);
    }

}

void loop()
{
    uPortTaskBlock(1000);
}

This works in that sense that I can connect with the u-blox Bluetooth Low Energy App on my phone and have the microcontroller echo messages that I send it via ble. However after first running the script the ble module seems to forget its Mac Address. When I request the address from the device with the command "AT+UMLA=1" it returns me an empty char, where previously it would have given me the full address (e.g. like "20BA360B67F4"). Also I am not able to send data anymore via the phyphox ble library but I havent really looked into how thats related. I tried this with two different NINA-B312 modules which are both not usable anymore after running this example script.

Any help or ideas would be appreciated

perssonmagnus commented 3 months ago

Hi Paula,

If I understand you correctly you are running this script and then immediately, without restarting the NINA-B312, trying to send AT commands over the UART via a terminal emulator or similar?

In that case the module will be in what is called Extended Data Mode, which is a u-blox proprietary protocol used over the UART to send AT commands and data packets. Refer to https://www.u-blox.com/docs/UBX-14044126 for details about this protocol.

If you restart the NINA-B312 it should go back to what we call command mode and be possible to contact again.

The different modes the module can use are described in the u-connectXpress user guide, https://content.u-blox.com/sites/default/files/u-connectXpress_UserGuide_UBX-16024251.pdf, chapter 3.2.1.

Best Regards, Magnus

PaulaScharf commented 2 months ago

Hi Magnus, Thank you so much for your input! Im turning the whole device off and on between running the script and then running a different script in which I am trying to send AT commands. Is that what you meant with restart? Otherwise I have also been trying to get back into command mode with these commands:

Serial1.print("AT+UMSM=0\r");
delay(100);
Serial1.print("AT&W0\r"); //write configuration to nonvolatile memory
delay(100);
Serial1.print("AT+CPWROFF\r"); //restart module into new configuration
delay(100);
Serial1.flush();
delay(2000);

But didnt work so far. Idk if these commands are even going through

m-abubakar commented 2 months ago

Hi @PaulaScharf, There should be two buttons marked 'SW1' and 'SW2' on the board, I believe pressing both together will put it back to command mode.

I will share the exact sequence of steps shortly (After verifying it on my end). Meanwhile you can try it and let me know if it works.

Thank you.

PaulaScharf commented 2 months ago

Hi @m-abubakar, sorry, I hadnt specified that yet. I am actually working with a custom ESP32-S2 based microcontroller (schematics if youre interested) to which I am connecting a ble module via XBEE (schematics of the ble module). I also read in the documentation something about using the DSR pin to get back into command mode. The Pin is exposed and addressable on our ble module, but I didnt get what I should do with it to get back to command mode

m-abubakar commented 2 months ago

Hi @PaulaScharf

Apologies for the delayed response; I was on vacation.

You can perform the factory reset as mentioned in my previous comment. Since you’re not using the EVK, here are the details about the switches:

SW1: Connected directly to the NINA (GPIO_7) pin
SW2: Connected directly to the NINA (GPIO_18) pin

To reset, ground these pins for 10 seconds. You may need to reset the module after this to see the changes.

For reference, you can view the EVK-NINA-B3 schematic in its user guide here: EVK-NINA-B3 User Guide

Let me know if this helps!