Go Down

Topic: Programma C# in continuo ascolto su seriale (Read 2207 times) previous topic - next topic

Nik_90

Ciao a tutti, premetto che ho girando un bel po su forum ma non avendo conoscenze solide mi viene difficile anche cercare su questo argomento.
Vi spiego, ho preparato un piccolo tool in C# che legge i dati seriali che vengono mandati da arduino. In particolare, ho arduino con un pulsante ed un led, in questo momento il programma ha un pulsante che, alla pressione, controlla lo stato del LED ed esegue un'azione. Per comodità posto il codice
Code: [Select]

public partial class MainForm : Form
{
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();

//configuring the serial port
serialPort1.PortName="COM3";
serialPort1.BaudRate=9600;
serialPort1.DataBits=8;
serialPort1.Parity=Parity.None;
serialPort1.StopBits= StopBits.One;

//opening the serial port
serialPort1.Open();
serialPort1.DiscardInBuffer();
//lettura = serialPort1.Read
}




void Button1Click(object sender, EventArgs e)
{

{

string comando = serialPort1.ReadLine();
string control = comando.Substring(0,6);



if (String.Equals(control, "SPENTO"))

{

Process.Start("IExplore.exe");
}


if (String.Equals(control, "ACCESO"))

{
Process.Start("notepad.exe");
}


}
}


Come vedete io premo il pulsante su arduino, il led si accende, ed invia una stringa.
Lato software io premo il pulsante, controllo la stringa (quindi lo stato) ed eseguo un'azione. In questo caso ho messo ad esempio il lancio di iexplorer.exe oppure notepad.exe.

Quello che io vorrei ora è che, il programma stesse sempre in ascolto! Cioè non devo eseguire ogni volta il check con il pulsante per vedere lo stato.

Quinid il programma sta in esecuzione, io premo il pulsante di arduino ed automaticamente mi si avvia il programma sul PC.

Come potrei risolvere?
Grazie mille!

flz47655

Se il programma non ha interfaccia grafica che deve aggiornarsi puoi fare un semplice ciclo infinito, l'applicazione sembrerà bloccata ma funzionerà.
In alternativa devi creare un Thread secondario, puoi usare il controllo backgroundworker per semplificarti la vita

Ciao

Nik_90


Se il programma non ha interfaccia grafica che deve aggiornarsi puoi fare un semplice ciclo infinito, l'applicazione sembrerà bloccata ma funzionerà.
In alternativa devi creare un Thread secondario, puoi usare il controllo backgroundworker per semplificarti la vita

Ciao


No il programma dovrebbe avere una minima interaccia grafica.. Almeno per quanto riguarda il settaggio della porta COM.. quindi l'interfaccia deve esserci. Per quanto riguarda quinid il backgroundworker stavo leggendo ora e sembra l'ideale, una cosa però? come dovrebbe avvenire il controllo sulla seriale? Una cosa del genere:
Code: [Select]

while serialport1.isopen..
{
if e condizioni varie..
}


potrebbe andare o sono fuori strada?! xD

astrobeed


No il programma dovrebbe avere una minima interaccia grafica.. Almeno per quanto riguarda il settaggio della porta COM.. quindi l'interfaccia deve esserci.


In C#, ma anche in C++, la seriale è un oggetto pertanto ha metodi, proprietà ed eventi, tra gli eventi devi avere qualcosa del tipo OnRxChar, o OnRxBuf, che puoi collegare ad una funzione, ovvero ogni volta che viene ricevuto un carattere viene richiamata la funzione collegata a questo evento.
In pratica ogni volta che arriva un carattere, o il buffer è pieno, sulla seriale la funzione che deve gestire la cosa viene richiamata automaticamente senza necessità di fare nessun polling, va da se che nel main loop dovrai comunque controllare dei flag, settati dalla funzione che gestisce la seriale, che ti indicano quale operazione eseguire.
Come va gestita la cosa in dettaglio dipende da quale compilatore ed eventuali librerie accessorie utilizzi, però il concetto generale che ti ho illustrato è valido per tutti i compilatori e sistemi operativi.

lucadentella

Ciao

in c# (o meglio in .Net Framework) la seriale ha una gestione "thread" interna, ovvero automaticamente viene generato un thread dedicato alla ricezione per non risultare bloccante.

Quello che tu devi fare è scrivere un tuo oggetto SerialDataReceivedEventHandler e aggiungerlo agli handlers dell'evento DataReceived:
http://msdn.microsoft.com/it-it/library/system.io.ports.serialport.datareceived.aspx

Molto importante se scrivi un programma con la GUI è l'utilizzo dei metodi delegate per aggiornare elementi dell'interfaccia grafica: se infatti provassi ad aggiornarli direttamente nel tuo handler, essendo questo eseguito in un thread separato, otterresti una exception (un po' come in java non puoi da un thread aggiornare componenti Swing ma devi sempre passare per lo SwingUtilities.invokeLater()).

Se vuoi un esempio completo guarda il mio progetto AnalogDemo:
https://github.com/lucadentella/AnalogDemo

bye
lucadentella.it

flz47655

In genere per risolvere queste situazioni devi usare un thread secondario e inserire il codice come quello che hai scritto bene o male.
Nel caso specifico del controllo SerialPort ti puoi semplificare la vita utilizzando gli eventi offerti dal controllo, ricordati di usare il metodo Invoke su un oggetto dell'interfaccia grafica per aggiornarlo.

Ciao

brexino

Potresti anche utilizzare un semplicissimo timer, che ad ogni giro, elabora i dati provenienti da seriali, con il vantaggio che l'applicazione non si blocca.

lucadentella

Ciao

non serve inventarsi Timers... gli handlers sulla ricezione seriale girano già in un altro thread e quindi non sono bloccanti
lucadentella.it

brexino

Dipende dalle applicazioni, anche perche con gli handler non puoi impostare un intervallo di lettura, invece impostando l'intervallo del timer a 1000 per esempio, nell'evento timer.tick, verrà eseguito un controllo sulla seriale ogni secondo, invece con gli handler, non si attiva ogni volta che riceve un dato?

Magari sbaglio io.

Go Up