Arduino UNO R4 - Commutare porta USB

:warning:
Un cattivo uso di quanto qui descritto e la non conoscenza del funzionamento di base della modalità DFU può portare all'impossibilità di caricare software sulla scheda. Si raccomanda di leggere attentamente questa discussione ed il reference del Arduino UNO R4 WiFi, nonché di studiarsi bene il "core" Arduino per tale scheda.


Come è possibile leggere nel reference di Arduino UNO R4 WiFi, vi è la possibilità di decidere se utilizzare la porta seriale tramite il bridge ESP32 (che è la modalità standard di Arduino UNO R4 WiFi) o utilizzare la USB nativa propria del Renesas, così come avviene su Arduino UNO R4 MINIMA.

Cominciamo a chiarire che, su Arduino UNO R4 WiFi, il pin D21 è riservato dal core per la selezione, appunto della porta seriale che si intende utilizzare ...

In pratica, di base, la comunicazione seriale avviene tramite ESP32 ... quindi, quando si fa Serial.begin(), su Arduino UNO R4 WiFi, viene creato un ponte tra in Renesas ed il ESP32 e le varie Serial.xxxxxx() passano attraverso tale ponte per uscire dalla USB che è collegata al ESP32.

Se però si mette il pin D21 a livello HIGH, si commuta il connettore USB da ESP32 a USB nativa del Renesas avendo così la possibilità di non usare il ponte tra Reneasa e ESP32, ma di andare direttamente sulla USB.

Ho voluto approfondire la cosa e, prima di entrare nei dettagli, vi dico già cosa si riesce a fare, cosa non sono riuscito a fare e cosa comporta la commutazione ...

  • Quello che si riesce a fare è che un programma .ino può, durante l'esecuzione, riuscire a commutare la seriale dalla classica Serial alla SerialUSB (nativa).

  • Quello che NON sono riuscito a fare e tornare indietro, ovvero, dopo essere passato alla SerialUSB, tornare alla Serial che passa via ESP32.

  • La commutazione di porta comporta che la Serial iniziale e la SerialUSB, si presentano, ovviamente, come due seriali diverse e quindi, al momento della commutazione la porta seriale che avevate aperto per parlare con la Serial viene disconnessa e viene creata una nuova porta seriale differente a cui vi dovete collegare per parlare con la SerialUSB.

  • Non solo, se si commuta, di nuovo, sulla Serial NON riappare la vecchia porta seriale, ma ci si trova in una situazione in cui NON si riesce più a comunicare con la seriale, né, tanto meno a caricare un nuovo programma (dato che non appare più la vecchia seriale che passa per l'ESP che provvede al caricamento). In questo caso, per caricare un nuovo programma si DEVE premere abbastanza velocemente due volte il pulsante di "reset" (per entrare in modalità boot), e, nell'IDE, selezionare la porta seriale che appare, dopo di che si può procedere, come al solito, nel caricamento di un nuovo programma.

Per fare le prove ho utilizzato, su macOS, un emulatore di porta seriale che mi permette di tenere aperte più finestre su più seriale che, ovviamente, appaiono ora connesse ora disconnesse, e che si auto-riconnettono da sole al riapparire di una seriale. In questo modo ho potuto tenere d'occhio quanto veniva stampato all'inizio sulla Serial, la sua disconnessione, la connessione su altra porta della SerialUSB e gli output da essa provenienti. Questo quello che ho ottenuto dal mio programmino dimostrativo, che allegherò più avanti, è questo:

Porta connessa a ESP32
[Connected]
Printing using ESP32
Now switching on USB
[Disconnected]

Porta connessa a USB nativa
[Connected]
Printing using USB
Switching back to ESP
[Disconnected]

... ma a questo punto NON si è riconnessa la porta collegata al ESP32 e non sono apparsi altri messaggi.

1 Like

Naturalmente ho provato ad inserire alcuni delay() pensando che magari potessero servire, ho provato a rifare il Serial.begin() dopo la riconnessione all'ESP32, ma nulla :frowning: ... non sono più riuscito a tornare indietro ed a riconnettermi all'ESP32.

Da notare che, essendo di base Arduino UNO R4 WiFi, collegato alla seriale tramite USB, per poter usare la USB nativa, occorre includere un .h (#include "tusb.h")ed inizializzare la USB nativa chiamando la __USBStart();

Ecco il codice di prova:

#if !defined(ARDUINO_UNOWIFIR4)
# error "This program is for Arduino Uno R4 WiFi"
#endif

#include "tusb.h"
#define USB_SW  21
#define USE_USB HIGH
#define USE_ESP LOW

uint8_t ledStatus = 0;

void setup() {
  delay (2000);
  pinMode( LED_BUILTIN, OUTPUT );
  digitalWrite ( LED_BUILTIN, ledStatus );
  pinMode ( USB_SW, OUTPUT );
  digitalWrite ( USB_SW, USE_ESP );
  Serial.begin ( 115200 );
  while ( !Serial ) delay(100);
  Serial.println ( "Printing using ESP32" );
  Serial.println ( "Now switching on USB" );
  delay(100);

  digitalWrite ( USB_SW, USE_USB );
  delay(100);
  __USBStart();
  delay(100);
  SerialUSB.begin ( 115200 );
  while ( !SerialUSB ) delay(100);
  SerialUSB.println ( "Printing using USB" );
  SerialUSB.println ( "Switching back to ESP" );
  delay(100);

  digitalWrite ( USB_SW, USE_ESP );
  delay(1000);
  Serial.begin ( 115200 );
  while ( !Serial ) delay(100);
  Serial.println ( "Printing using again ESP32" );
  Serial.println ( "Program ended" );
}

void loop() {
  ledStatus = ~ledStatus;
  digitalWrite ( LED_BUILTIN, ledStatus );
  delay(500);
}

Naturalmente, se qualcuno sa come modificare/migliorare il programma, ben venga ... con la speranza di venirne a capo :grin:

Buone prove e ... attenzione a non rendere inutilizzabile il Arduino UNO R4 WiFi ... :wink:

Guglielmo