Raspberry Pi Pico W - doppia porta seriale - via bluethooth e via USB

Piattaforma PlatformIO - framework: Arduino - board: rpipicow - core: earlephilhower
S.O.: windows 10 - Scheda: Raspberry Pi Pico W

Ho una scheda Pico W collegata al PC tramite cavo alla porta USB che crea una porta seriale tramite USB (su PC viene ad esempio identificata come COM4); la stessa scheda è collegata allo stesso PC anche tramite bluetooth con libreria SerialBT (rfcomm) (su PC viene ad esempio identificata come COM5 e COM6).

Ho attualmente un programma che funzionava solo col collegamento seriale via USB che richiama sempre la funzione "Serial." per comunicare col PC (il programma è lungo e richiama la funzione "Serial." molte volte e non vorrei fare molti cambiamenti).

Da programma su Pico W vorrei scegliere se usare la seriale USB o la seriale Bluetooth per trasmettere i dati al PC, lasciando comunque tutte le chiamate inalterate a 'Serial.".

Potrei farlo in sede di compilazione con una #define Serial SeriaBT, ('Serial' usa seriale USB - 'SerialBT' usa seriale Bluetooth), ma vorrei invece decidere in sede di esecuzione del codice a seconda di alcune scelte.

Esiste un metodo per assegnare 'dinamicamente' (non so se mi sono spiegato bene), la funzione 'Serial' ad un'altra funzione che comunque ha gli stessi metodi ?
In pratica ad un certo punto del codice, in base ad alcune condizioni, dire che la funzione Serial, pur lasciandola scritta così com'è, mi richiami la funzione SerialBT .

Dovrebbe essere possibile
Con poche modifiche al programma

Devi fare un cerca e sostituisci, perchè la parola serial è già usata

La cambi in qualcosa d'altro

Devi poi dichiarare un oggetto stream usando il nuovo nome

Poi al bisogno puoi valorizzarlo a Serial o a SerialBT

Dovrebbe andare

Anni fa qualcuno lo aveva già trattato, non ricordo quando ne chi
Magari qualcun altro ricorda

Io voglio però mantenere il nome 'Serial' nel codice; voglio abbinarlo all'occorrenza alla funzione SerialBR.

.. come farebbe "#define Serial SeriaBT" ma dinamicamente in esecuzione

1 non puoi
Serial è parola riservata, non puoi usarla per altro

2 come ti ho detto
Usi un oggetto stream di volta in volta valorizzato agli stream che vuoi usare

Non sono sicuro che vada, ma la vedo come unica strada

Potresti farmi un esempio di codice veloce che non sono tanto esperto e poi faccio delle prove ?
Ipotizziamo che cambio tutte le parole 'Serial' con 'SerialOF' (quindi nel codice ad esempio al posto di Serial.read ci sarà SerialOF.read, al posto di Serial.avaliabe() ci sarà SerialOF.avaliable(), al posto di Seria.printf("Prova") ci sarà SerialOF.printf("Prova"), ecc.ecc.).
Io devo, a seconda di una condizione, quando richiamo SerialOF, far eseguire o 'Serial' o 'SerialBT' (i metodi sono gli stessi, ma cambia l'implementazione, il primo fa seriale su USB e l'altro la fa tramite Bluetooth)
Per il momento grazie.

Nessuno ricorda a parte me
Magari dipende dal fatto che sono stato io a scriverlo
qui:

attenzione, che come lo usate voi non va
bisogna usare un "puntatore" a Stream, gli oggetti stream non sono assegnabili

anzi visto che ai tempi non era stato provato, anzi era stato ignorato:

provatelo voi, che se va lo metto nel mio la pappa è fatta, che nel frattempo il prode Anselmo, ops il buon Guglielmo, riapre, vero? grazie

Bè, se ti riferisci alle indicazioni che allora hai dato a me, sì che lo avevo provato. E funzionava (funziona) piuttosto bene.
In sostanza, lato arduino Mega (sul quale agisce il TFT per i comandi, anche di commutazione seriale):

Stream* MYSERIAL;
...
 
  Serial1.begin(BAUD1);      // via cavo
  Serial2.begin(BAUD2);      // via Bluetooth (MASTER)
  
  MYSERIAL = &Serial1;      // Default via cavo

Successivamente, sintetizzando, tramite TFT, dò la stringa di commutazione seriale per attivare il bluetooth lato Arduino Due (e Mega, contemporaneamente).

MYSERIAL->print(":BTON#");  // Bluetooth On

Il alto Arduino Due recepisce la stringa (ometto la parte di recepimento e lettura stringa) e dà il comando:

  
    MYSERIAL = &Serial2; // Arduino Due commuta in bluetooth

Sto andando a memoria perché si tratta di un vecchio progetto, che però funziona molto bene. Come richiede l'autore del post, è un comando dinamico, che funziona per commutare la seriale da bluetooth a cavo, e viceversa, tra due unità Arduino.
Ciao

Grazie ... gentilissimi .. dopo lo provo
.. altra DOMANDA:
.. c'è un modo per scrivere "MYSERIAL.print(":BTON#");" anzichè "MYSERIAL->print(":BTON#");"
..ovvero il '.' anzichè '->' ?

comunque noi avevamo anche scritto un programmino di prova:

/*
   Una nuova idea DDD
   Del Dinamico Duo

   Sentitevi liberi di copiare
   Sentitevi liberi di trarre ispirazione
   Sentitevi liberi di dare un cenno di ringraziamento

   // su ispirazione di una vecchia discussione, che non troviamo più
   // trovata: era di Standardoil,

   Creato con IDE 1.8.10
*/

#include <SoftwareSerial.h>
// solo per avere una seconda seriale

SoftwareSerial mySerial(10, 11); // RX, TX

Stream * flusso;

void setup()
{
   mySerial.begin(9600);
   Serial.begin(9600);
}

void loop()
{
   flusso  =  & Serial;
   // commuto su una seriale
   delay(100);
   flusso->print("01 ");
   // occhio all'uso dell'operatore freccia, invece dell'operatore punto
   // obbligatorio se si tratta di puntatori ad oggetti invece degli oggetti puntati
   flusso  =  & mySerial;
   //commuto sull'altra
   delay(100);
   flusso->print("02 ");
}

e confermiamo che funziona, tra due UNO

Mi rispondo da solo, vi chiedo solo la cortesia di confermarmi che ciò che dico è corretto:
supponendo:

Stream* MYSERIAL;
MYSERIAL = & Serial;

.. scrivere (*MYSERIAL).print("prova") è equivalente a scrivere MYSERIAL->print("prova");

Giusto ?

..a questo punto potrei semplicemente sostituire tutti i Serial.read(), Serial.begin(), Serial.peek(), ecc.ecc. in (*MYSERIAL).read(), (*MYSERIAL).begin(), (*MYSERIAL).peek(), ecc.ecc.

..e potrei farlo con una #define Serial (*MYSERIAL)

Il sistema che ho scritto sopra funziona, l'ho provato. .... ma
La Classe Stream (comune sia a Serial che a SerialST che la derivano), non ha però la definizione dell'operatore bool, che invece hanno le classi Serial e SerialBT che serve per sapere se la connessione è attiva (if (Serial) print("Connessione via cavo attiva") .. if (SerialBT) printf("Connessione bluetooth attiva");.
Pertanto il sistema studiato funziona per tutte le chiamate, ad eccezione dell'operatore 'bool' per capire se la connessione è attiva, questo perchè la classe virtuale Stream non prevede la definizione di tale operatore, che viene invece implementata nelle classi Serial e SerialBT.
Pertanto vi chiedo se avete qualche idea ?

Perduna ma a me non torna quello che hai detto nell'ultimo post

Me lo spieghi ?

In che senso Ducembarr?

... guardando i sorgenti vedo che l'operatore booleano, che ti da lo stato della porta seriale, è effettivamente definito nella classe Serial e non nella classe Stream, oltretutto, nella Serial ritorna sempre e solo "true" mentre nella SerialUSB (che poi è la seriale usata dalle schede con USB nativa), fa effettivamente le dovute verifiche e ritorna di conseguenza.

Che cosa non ti torna di questo? :thinking:

Guglielmo

ma questo era chiarissimo

solo a me sembrava ovvio che si sarebbe scelta la seriale da usare "dopo" aver capito quale fosse quella che andava

... credo che voglia fare tutto dinamicamente cambiando l'assegnazione allo stream "flusso" :roll_eyes:

Guglielmo

E lo può fare

Solo che il test serve farlo 'prima'
Non a compile-time, a run-time ma prima del cambio

Ho anche un altra domanda, se riuscite ad aiutarmi.
Quando associo tramite bluetooth la prima volta il pico w a windows (servizio HID + serialBT (rfcomm)), windows me lo riconosce, configura regolamente i dispositivi, lo associa e lo connette. Se spengo tutto, quando riaccendo mi trovo ancora il dispositivo associato, ma non si connette in automatico. Qualcuno sa come posso fare per farlo connettere in automatico ? Immagino che debba impostare qualcosa con le funzione di configurazione del 'gat', non so, sto andando un po' a tentativi.
Le attuali impostazioni del 'gat' che ho sono le seguenti.
gap_discoverable_control(1);
gap_set_class_of_device(hidClass);
gap_set_local_name(localName);
gap_set_default_link_policy_settings(LM_LINK_POLICY_ENABLE_ROLE_SWITCH | LM_LINK_POLICY_ENABLE_SNIFF_MODE);
gap_set_allow_role_switch(true);

.... ed alla fine attivo il bluetooth con:

hci_power_control(HCI_POWER_ON);

Grazie per la disponibilità e le dritte

Potevi dirlo due anni fa, magari sarebbe stato utile ad altri

L'ho detto. Evidentemente, due anni fa, ti era sfuggito:

Non so se creare un nuovo post ... ma prima provo qui
Quando tramite il Pico W e la libreria SerialBT creo una porta seriale Bluetooth sul PICO W che poi associo a Win10, mi vengono create su windows due porte COM, una delle quale inutilizzabile in quanto risulta perennemente occupata. Utilizzando l'altra (che presumo sia una sorta di collegamento virtuale all'altra), non riesco ad inviare dati e pure inviando dati dal pico W verso windows non ricevo nulla. Qualcuno ha già avuto stesso problema ed ha risolto. E' da un po' che cerco soluzioni, ma non ho trovato ancora nulla.