Send BLE data trough BLE with Arduino RP 2040 Connect

Hello, I've read all the similar topics and I'm here to ask your help. I'm trying to connect my Arduino RP2040 to App Inventor, but when I try to send rssi data as strings to App Inventor nothing happens except an error: "Service ..., characteristic ...the are not published by the connected device". I've tried also to use integers or bytes but nothing works.
Notes: with nRF Connect all works fine, so the UUIDS are right and the code is working well.
These are my blocks:

And this is my Arduino code, it need to check the RSSI if is it low send a notification trough Telegram and Blynk, to do that I need to turn off the BLE module of my rp2040, then restart it again after the notification sent.

#include <ArduinoBLE.h>
#include <WiFiNINA.h>
#include <WiFiSSLClient.h>
#include <UniversalTelegramBot.h>
#include <math.h>

// ------ credenziali Blynk ------
#define BLYNK_TEMPLATE_ID "XXXXXXXX"
#define BLYNK_TEMPLATE_NAME "BLE geolocalization"
#define BLYNK_AUTH_TOKEN "XXXXXXXXXXX"
#include <BlynkSimpleWiFiNINA.h> // deve rimanere qui fissa non spostare

// ------ credenziali Wi-Fi ------
char ssid[] = "XXXXXXX";
char password[] = "XXXXXXXXXX";

// ------ credenziali Telegram ------
#define BOT_TOKEN "XXXXXX:XXXXXXXXXXXXXXXXXXXXXXX" // token bot Telegram
#define CHAT_ID   "XXXXXXXX"

// ------ inizializzazione variabili ------
WiFiSSLClient client; // gestisce la connessione sicura (SSL)
UniversalTelegramBot bot(BOT_TOKEN, client);

BLEService alertService("12345678-1234-5678-1234-56789abcdef0"); // UUID custom
BLEStringCharacteristic alertChar("abcdef01-1234-5678-1234-56789abcdef0", // 7
BLERead | BLENotify, 20);

const int SOGLIA = -65; // soglia di allontanamento
const int SOGLIA_OK = -60; // soglia di ritorno (hysteresis)
bool alertPending = false;
bool alertSent = false;
String strValue = "0";
const int measured_pw = -57; // potenza misurata a 1 metro di distanza
const float n = 2.0; // attenuazione dello spazio libero (2-4) indoor

// ------ funzioni ------
bool inviaNotifica(int rssi,  float distance) {
  Serial.println("Connessione WiFi per inviare notifica...");
  int status = WiFi.begin(ssid,password); // accendo il modulo Wi-Fi
  unsigned long startAttempt = millis();

  // aspetto la corretta attivazione del Wi-Fi entro 10 secondi
  while (status != WL_CONNECTED && millis() - startAttempt < 10000) {
    delay(500);
    status = WiFi.status(); // controlla lo stato della connessione
    Serial.print(".");
  }

  // se connessione non riuscita vai avanti senza ritentare
  if (status != WL_CONNECTED) {
    Serial.println("\nErrore WiFi: impossibile inviare notifica, continuo il programma...");
    return false;
  } else {
      Blynk.begin(BLYNK_AUTH_TOKEN, ssid, password); // avvia la sessione Blynk solo se il wi-fi è attivo
      Serial.println("WiFi connesso âś…");
  }
  delay(200);

  // ------ notifica Telegram ------
  String messagge = "Attenzione! Il telefono si è allontanato.\n";
  messagge += "Ultimo RSSI = " + String(rssi) + " dBm.\n" + "La distanza stimata è pari a " + String(distance,2) + " metri";
  bool ok = bot.sendMessage(CHAT_ID, messagge, ""); // comando di invia notifica
  Serial.println(ok ? "Notifica inviata" : "Errore invio notifica Telegram"); // informa l'utente sull'esito della notifica

  // ------ notifica Blynk IoT -------
  Blynk.virtualWrite(V0, distance);
  Blynk.virtualWrite(V1, rssi);
  Blynk.logEvent("distance_alert", "⚠️ Ti sei allontanato troppo! d = " + String(distance,2) + " metri");
  delay(1000); // aspetta prima di chiudere la sessione con il server di Blynk
  Blynk.disconnect();
  WiFi.disconnect();
  delay(500); // permette la corretta disconessione
  WiFi.end(); // termina il modulo Wi-Fi

  return ok;
}

// avvia il modulo BLE del RP2040
void startBLE() {
  if(!BLE.begin()){
    Serial.println("Starting BLE module failed!");
    while(1);
  }
  Serial.println("Successfully BLE module activeted!");
  BLE.setLocalName("RP2040");
  BLE.setAdvertisedService(alertService); // setto caretteristica e servizio
  alertService.addCharacteristic(alertChar);
  BLE.addService(alertService);
  BLE.advertise(); // Arduino inizia a fare advertising
}

// ------ setup ------
void setup() {

  Serial.begin(115200);
  while(!Serial); // aspetta che il monitor seriale sia pronto
  startBLE(); // inizializzo il modulo BLE
  alertChar.writeValue(strValue);

}

// ------ loop ------
void loop() {
  BLEDevice central = BLE.central();
  // ottiene rssi se connesso e calcolo distanza
  if (central && central.connected()) {
    int rssi = central.rssi();
    strValue = String(rssi);
    float distance = pow(10,((measured_pw-rssi)/(n*10)));
      if (rssi == 127){
        Serial.println("Telefono disconnesso! (RSSI= 127)");
      } else {
          Serial.print("RSSI = ");
          Serial.println(rssi);
      }
      alertChar.writeValue(strValue);
      delay(200); // serve per far arrivare correttamente ad app inventor il messaggio
      // logica soglia
      if (rssi < SOGLIA && !alertSent) {
        alertPending = true;
      } else if (rssi > SOGLIA_OK) {
        alertSent = false;  // reset
      }

      // invio notifica se serve
      if (alertPending) {
        BLE.end(); // spengo il modulo BLE così da evitare conflitti
        if (inviaNotifica(rssi,distance)) {
          Serial.print("La distanza stimata del dispositivo è : ");
          Serial.print(distance);
          Serial.println(" metri");
          alertSent = true;
          alertPending = false;
        } else {
            alertPending = false; // se la inviaNotifica fallisce il programma va avanti
        }
        startBLE();
      }
      }
      else {
        Serial.println("Telefono non connesso, ritenta connessione...");
      }
    
  delay(3000); // ogni 3 sec ripeto il ciclo
}

CIao @giusesciac (Giuseppe ?),
visti i commenti del tuo file Arduino in Italiano, faccio che risponderti in italiano, poi se non riusciamo a risolvere, usiamo l'inglese, così anche altri PU possono intervenire.
Come primo consiglio, ti dico di "spezzare" il tuo codice in due parti: ovvero, prima prova un codice molto semplice che ti permetta di verificare che la connessione BLE funziona, poi ci aggiungi il resto. Se no hai troppe cose che messe assieme tutte subito possono inficiare il buon funzionamento.

A questo proposito ti allego due files, un .aia che permette la connessione BLE ad una ESP32 (in realtĂ  questa app connette anche un BT classico di un'altra scheda, ma ma tu non farci caso, e concentra la tua attenzione solo sulla parte BLE).
Il secondo file è il codice Arduino (per ESP32, non ho un RP2040)) che si presenta con il suo Servizio, la sua Caratteristica e con il nome della rete "UART Service" (che è quello che viene cercato dalla App). Nota che nella App ho due clock: il primo per lo scan, e dopo che lo scan ha ottenuto la connessione con "UART Service", fa partire il secondo clock, per la "register for string". Dopodiché ad ogni pressione di un tasto (A,B,C) invia tramite il BLE il carattere corrispondente alla ESP, la quale lo visualizza su Serial Monitor e lo manda indietro alla app, così si chiude il loop di Tx e Rx..

Ti consiglio quindi di provare prima questi due semplici codici di esempio, poi, una volta che ha una connessione funzionante, ci costruisci sopra il resto.
Best wishes and happy coding !
BLETestAI2_uart.ino (5.9 KB)
BLE_Test.aia (257.5 KB)

Hi Ugo, yes my name is Giuseppe. Your example is working well, this evening I’ll expand your application to mine and let’s see. Thank you for your help!

1 Like

Glad that it helped you !
Feel free to ask whenever any issue arises.

Ciao, Ugo.