[RISOLTO] Problemi di comunicazione Seriale - Arduino UNO R4 Minima + Form Visual Basic

Salve a tutti, sono nuovo nel forum e spero di poter trovar aiuto e nel caso aiutare tutte le persone che riscontrano il mio problema.

Il mio obiettivo è quello di interfacciarmi con Arduino (In questo caso R4 Minima) tramite un programmino creato con Form Visual Basic.
In poche parole il programma non fa altro che fare una scansione delle COM, selesionare la COM desiderata e connettersi. Con ulteriori due tasti gli mando una stringa in seriale che corrisponde a "start" e "stop". L'arduino risponderà accendendo o spegnendo il LED_BUILTIN.

Qual'è il problema? Beh, lo stesso codice di arduino si comporta diversamente tra:
Arduino UNO R3 e Arduino UNO R4 Minima (Giustamente montano micro diversi)
Nel codice riportato è riportato anche lo stepper ma non lo sto utilizzando.

#include <Stepper.h>

#define GIRO 2746 * 1

const int step_rot = 24;
const int vel = 24;
const int step_tot = GIRO;
const int step_mov = 1;
int step = 0;

Stepper bipolar(step_rot, 8, 9, 10, 11);

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  bipolar.setSpeed(100);
}

void loop() {
  if (letturaSeriale().equals("start")) {
    digitalWrite(LED_BUILTIN, HIGH);
    for (int i = 0; i < GIRO; i++) {
      if (letturaSeriale().equals("stop")) {
        digitalWrite(LED_BUILTIN, LOW);
        break;
      }
      bipolar.step(step_mov);
    }
  }
}
String letturaSeriale() {
  String comando = "";
  char c;
  unsigned long startTime = millis();
  unsigned long timeout = 1000;
  while (millis() - startTime < timeout) {
    if (Serial.available()) {
      c = Serial.read();
      if (c == '\n' || c == '\r') {
        comando.trim();
        return comando;
      } else {
        comando += c;
      }
    }
  }
  return "";
}

Utilizzando Arduino UNO R3 funziona tutto regolarmente, premo il mio pulsante e invio la stringa "start" e il led si accende.
Lo stesso codice con Arduino UNO R4 Minima invece ha un comportamento strano.. La COM sembra connettersi, ma quando gli mando il comando ("start") non accade nulla.
Ho provato in diversi modi, premendo il tasto reset, mettendogli un while alla seriale ma niente. Nel momento in cui mi collego con il monitor seriale di arduino (dopo essermi connesso con il programmino e avergli inviato le stringe), il LED_BUILTIN si accende, come se il messaggio fosse rimasto in coda. Questo non accade con l'altro Arduino.

Vi condivido anche il codice del Form Visual Basic anche se magari potrebbe interessare di meno:

Public Class Form1

    'ESECUZIONE AL CARICAMENTO DEL FORM
    Dim connection As Boolean = False
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        Button1.PerformClick()
        SerialPort1.NewLine = vbLf
    End Sub

    'TASTO AGGIORNA
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ComboBox1.Items.Clear()
        ComboBox1.Items.AddRange(IO.Ports.SerialPort.GetPortNames())
        Console.WriteLine("Aggiornamento COM")
    End Sub

    'TASTO DI CONNESSIONE/DISCONNESSIONE
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        If connection Then
            SerialPort1.Close()
            Console.WriteLine("Disconnesso")
            connection = False
        Else
            SerialPort1.Encoding = System.Text.Encoding.Default
            SerialPort1.PortName = ComboBox1.Text
            SerialPort1.BaudRate = TextBox1.Text
            If ComboBox1.Text <> "Seleziona.." Then
                SerialPort1.Open()
                Console.WriteLine("Connesso")
                connection = True
            End If
        End If

    End Sub

    'PULSANTE START
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        SerialPort1.WriteLine("start")
        Console.WriteLine("start")
    End Sub

    'PULSANTE STOP
    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
        SerialPort1.WriteLine("stop")
        Console.WriteLine("stop")
    End Sub
End Class

Cattura

Aggiungo che mi sono assicurato che il Form Visual Basic invii le stringhe con il terminatore finale '\n'

Come posso risolvere questo problema? C'è qualche impostazione aggiuntiva che bisogna dare a codice ad arduino per la gestione della seriale?
Fatemi sapere vi ringrazio.

Arduino UNO R4 ha una USB nativa e quindi ... DEVI aspettare che sia pronta ... guarda il reference QUI.

Guglielmo

Grazie Guglielmo per la risposta, ho dato una letta al reference che mi hai condiviso.

Ho aggiunto il while che attende la connessione e in più ho aggiunto un lampeggio del LED_BUILTI per capire quando si connette.

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ;
  }
  pinMode(LED_BUILTIN, OUTPUT);
  //bipolar.setSpeed(100);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);
}

Purtoppo questo non sembra risolvere il problema..

Ho aggiunto anche una verifica in più su visual basic per verificare che sia effettivamente connesso prima di inviare il comando:

    'PULSANTE START
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        If SerialPort1.IsOpen Then
            SerialPort1.WriteLine("start")
            Console.WriteLine("start")
        End If
    End Sub

    'PULSANTE STOP
    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
        If SerialPort1.IsOpen Then
            SerialPort1.WriteLine("stop")
            Console.WriteLine("stop")
        End If
    End Sub

Per Visual Basic la connessione alla COM sembra esserci, ma da parte dell'arcuino no.
Il led in questo caso lampeggia solo se mi connetto con il monitor seriale di arduino ide.

io proverei un semplice echo della seriale per vedere cosa riceve.

Il monitor seriale di Arduino IDE quando si connette ad una seriale non nativa fa un reset della scheda usando il pin DTR dell'interfacca USB/TTL.

Con le schede tipo la Uno R4 invece, da quanto ho letto qui sul forum, sembrerebbe che per fare il reset della scheda venga aperta e chiusa la COM con un baudrate di 1200 bps.

Ho provato ad aggiungere al mio codice di Visual Basic l'apertura e la chiusura della COM a baud rate 1200, questo però sembra mandare l'arduino in Boot DFU e ci rimane, senza fare il reset. Ho utilizzato una pausa di 500ms tra apertura e chiusura della COM, non so se bisogna rispettare un certo tempo per poterlo mandare in reset.

E se provi a fare due volte quest'operazione che succede?
Con Arduino IDE quando fai l'upload del codice, prima la scheda viene messa in DFU mode, ma quando l'invio è terminato viene nuovamente resettata per avviare il firmware.

apro/chiudo a 1200 -> DFU
un piccolo delay
apro/chiudo a 1200 -> reset (?)

Normale, contrariamente alle vecchie schede, nella UNO R4 il caricamento del programma NON avviene via serial, ma via USB DFU, quindi, se forzi la funzione di reset, la scheda si mette in USB DFU.

Guglielmo

Non si può fare.. Perchè mandando la scheda in boot la COM sparisce.
In questo caso penso che arduino ide gestisca la programmazione direttamente tramite il DFU una volta in boot.
Comunque avevo provato a mandargli dei comandi(stringhe) anche da altri programmi che fanno da monitor seriale ma non sembrano funzionare nemmeno loro.
Al di fuori che io stia usando un form di visual basic, il problema si presenta lo stesso.
Probabilmente ci sarà il modo di fare il reset.. E' solo da capire come..
Proverò a leggere il datasheet del micro per vedere se trovo qualcosa.

Tienici aggiornato.
Questa sera per curiosità provo con un Nano 33 IoT (nRF52840).

Con gli ESP32 (S2, S3, C3 etc etc) dotati di USB nativa questa cosa non accade (anche se io di solito uso QT/C++ per sviluppare applicazioni PC).

Son guardando il datasheet, ma per il momento non trovo nulla di utile:
Datasheet Renesas RA4M1
USB -> Pag. 601

Non sono sicuro, ma penso che se vuoi usare la seriale via cavo USB devi usare SerialUSB al posto di Serial.

Ciao.

dal cheat sheet:

SerialUSB

The UNO R4 WiFi has an extended set of Serial methods that can be enabled whenever you include the

<HID.h>

library in your sketch.

    Serial.baud()

    - Returns the baud rate (int) currently used.

    Serial.stopbits()

    - Returns the number of stop bits (int) used in the communication.

    Serial.paritytype()

    - Returns the type of parity (int) used in the communication.

    Serial.numbits()

    - Returns the number of data bits (int) used in the communication.

    Serial.dtr()

    - Returns the status of the Data Terminal Ready (DTR) signal (bool) and also sets the- ignore_dtr flag to true if the DTR signal is actively used.

    Serial.rts()

    - Returns the status of the Request to Send (RTS) signal (bool).

The <HID.h> library remaps the Serial object to SerialUSB, which enables these additional features. 

riprendo il mio primo messaggio...magari lo hai già fatto...ma inviare dalla scheda un qualche cosa e mettere un programma in ascolto?...se funziona, quindi c'è trasmissione, provare a leggere carattere per carattere quello che arriva e scriverlo in un LCD (o altro monitor/visualizzatore)?

Scusami se non ho risposta ad un tuo precedente messaggio.
Comunque se fosse una seriale RX TX si potrebbe collegarsi esternamente e leggere quello che passa. Ma purtroppo in questo caso è direttamente USB da PC a micro.
Dovrei provare a farmi inviare una risposta da arduino se rileva qualcosa nella seriale..
Darò un occhiata anche alla parte che mi hai condivido sopra del cheat sheet, potrebbe tornare utile. Forse c'è qualche modo particolare per inviargli dei dati di reset.
Verso sera vi aggiorno

Ciao Mauro, ho provato con SerialUSB, aggiungendo solo "USB" a serial e al momento si comporta come prima, ma ho guardato alla svelta, forse bisogna importare qualche libreria o aggiungere parti di codice mancanti. ti faccio sapere, grazie

Come accennavo più su, ho fatto una prova con un nRF5840 (ho usato una XIAO al posto del nano, ma tanto sono lo stesso microcontrollore).

Ho preso uno sketch di esempio che crea una porta seriale USB CDC (Communication Device Class) ed ho inserito il classico while nel setup()

// Create extra USB Serial Ports.  "Serial" is already created.
Adafruit_USBD_CDC USBSer1;
...
 while (!USBSer1) {
  etc etc
}

Con il monitor seriale lo sketch si avvia come previsto, ma usando un terminale software diverso (YAT, Yet Another Terminal) rimane in pausa fintanto che non "abilito" il segnale DTR.

Si tratta di una seriale USB come puoi vedere dal print screen, ma evidentemente a livello di protocollo USB, il segnale DTR che corrisponderebbe ad un'uscita logica in una seriale "normale", fa avviare correttamente la comunicazione seriale.
Immagino venga emulato il controllo di flusso hardware in modo da avere piena compatibilità "null modem".

Facendo vari test mi sono accorto che con determinati programmi si riesce a comunicare.. Anch'io ho usato YAT e sembra funzionare. Pyhton configurato nel modo corretto funziona.
Probabilmente Visual Basic utilizza un metodo vecchio di comunicazione o driver vecchi.
Provo a controllare se ci sono aggiornamenti recenti di Visual Basic ed effettuo ulteriori prove.
Sicuramente ci saranno molti altri programmi simili a visual basic per creare interfacce personalizzate, ma dal momento che conosco abbastanza bene Visual Studio, mi dispiacerebbe dover cambiare programma. Anche se dovrò farlo se non trovo soluzioni..
Riusciresti a farmi una lista di programmi alternativi che non siano a pagamento?
Fammi sapere, ti ringrazio!

Come detto io uso il framework Qt un po' per tutto.

Sostanzialmente è C++, ma questo framework è un po' un mondo a parte ed ha già le sue API praticamente per tutto.
Un altro grande vantaggio è la portabilità del software: lo stesso sorgente compila con ogni sistema operativo senza troppo impegno (di base il progetto vorrebbe configurato in automatico).

Se sei interessato, ti posso girare il sorgente di un progettino nato per controllare il pan/tilt di una videocamera che fa più o meno quello che fa il tuo adesso.

Volentieri, mi farebbe piacere per avere già un esempio di codice.

Ma Framework Qt è a pagamento? o c'è qualche versione ad uso personale? Io non devo nulla di serio, ho più intenzioni da hobbista.