In seguito a diverse prove, sono qui a chiedervi un'aiuto in merito all'estrapolazione di dati ricevuti via seriali al pc.
In pratica, dispongo di un sensore di colore, che attraverso l'elaborazione di arduino, riesce a inviarmi via seriale i tre valori rgb dell'oggetto posto difronte al sensore proprio così come di seguito:
R: 255
G:255
B:255
In sintesi, i valori RGB dell'oggetto posto difronte al sensore, vengono inviati ciascuno su una riga differente.
Come potrei riuscire ad assegnare ognuno di questi valori una variabile così da poterli gestire in visual basic 2010?
Come al solito, è meglio agire con progressività.
Lascia stare i TRE dati.
Dimmi se UN dato riesci a leggerlo da VB. Fatto questo, il resto sarà semplicissimo.
Buonasera.
In realtà ci stavo guardando, però non sono riuscito a capire granchè in rete.
Ti posto qui di seguito il codice che ho scritto fin ora...
Praticamente avvio un timer con intervallo = 1000 ms. Mi scrive "A" sulla seriale precedentemente settata e aperta.
Aspetta 1000 ms, tempo nel quale di aspetta di ricevere da arduino i valori di RGB facenti riferimento alla richiesta inviata con il carattere "A".
L'unica cosa è che non ho proprio idea di come andare a prelevare l'integer dopo i caratteri "R,G e B" e assegnarlo a una variabile.
Avresti qualche suggerimento per aiutarmi?
Grazie mille.
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
SerialPort1.Write("A")
SerialPort1.ReadTimeout = 1000
data = SerialPort1.ReadExisting()
'dovrei leggere dopo la R e associare il valore a una red1'
'dovrei leggere dopo la G e associare il valore a green1'
'dovrei leggere dopo la B e associare il valore a blue1'
PictureBox1.BackColor = Color.FromArgb(red_slot_1, green_slot_1, blue_slot_1)
End Sub
Quindi sono TRE invii, uno per R, uno per G ed uno per B.
Visto che il formato è sempre X:numero, dove X: può essere R:, G:, B:, potresti leggere tre stringhe e su ciascuna splittare al terzo carattere, poi fai da stringa a numero sulla seconda parte. Puoi usare la prima parte per sicurezza per sapere se stai leggendo R, G, B.
Il timeout 1000 ms lo toglierei... puoi anche modificare il timer a 100 ms se ti serve una maggiore fluidità nell'aggiornamento dei valori.
Ecco quello che sono riuscito ad ottenere fin ora.
Però mi sembra che manchi qualcosa.
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If slot1_flag = 1 And SerialPort1 IsNot Nothing Then
SerialPort1.Write("A")
SerialPort1.ReadTimeout = 1000
data = SerialPort1.ReadLine()
If InStr(1, data, "R", CompareMethod.Binary) = 1 Then
red_slot_1 = Microsoft.VisualBasic.Right(data, 3)
ElseIf InStr(1, data, "G", CompareMethod.Binary) = 1 Then
green_slot_1 = Microsoft.VisualBasic.Right(data, 3)
ElseIf InStr(1, data, "B", CompareMethod.Binary) = 1 Then
blue_slot_1 = Microsoft.VisualBasic.Right(data, 3)
End If
Ho lasciato il timeout, perchè la procedura di lettura e scrittura in seriale dei valori ricavati dal sensore, prende circa 500 ms.
Non vorrei che il visual basic leggesse quando i valori non sono ancora arrivati.
Attualmente nel debug non ricevo nessun errore, però non so se le funzioni che uso per manipolare le stringhe sono adeguate.
E poi, hai qualche idea su come possa leggere ogni riga separatamente delle tre righe che mi arrivano in seriale?
Con la funzione "SerialPort1.ReadLine()" credo che riuscirei a leggere solo una riga e basta. Giusto?
Puoi anche leggere una sola riga alla volta, come nel caso I.
Però devi dirgli di leggere TRE VOLTE, così legge le tre righe.
Oppure in alternativa ti scegli un fine dati, qui ipotizziamo che sia il carattere "E",
e trasmetti
R:230
G:122
B:255
E
Potresti avere difficoltà con cifre con meno di tre caratteri come
G:24
oppure
B:9
quindi anche nel primo caso ti conviene usare lo split mediante ":" e poi leggere il valore dei due pezzi, uno ti dice se stai leggendo R, G o B - e sarebbe anche inutile visto che li trasmetti in sequenza e già sai che il primo sarà R e così via - l'altro pezzo invece contiene il valore.
Infine... faresti bene a convertire da caratteri ad int
sto andando un pò a tentativi perchè non sono molto pratico di VB.
Ad ogni modo, credi che il seguente codice sia pertinente con quanto mi hai detto?
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If slot1_flag = 1 And SerialPort1 IsNot Nothing Then
SerialPort1.Write("A")
SerialPort1.ReadTimeout = 1000
For counter As Integer = 0 To 3
data = SerialPort1.ReadLine()
data_array = Split(data, ":", 2)
Next
data_array(0) = red_slot_1
data_array(1) = green_slot_1
data_array(2) = blue_slot_1
Return
Else
Return
End If
End Sub
0 to 3 ti legge 4 volte e credo che l'assegnazione fuori dal for sia fatta al contrario...
secondo me stai facendo più complicazioni del dovuto
mentre sei nel for potresti assegnare color(counter) dove hai
color(0) = valore R
color(1) = valore G
color(2) = valore B
ovviamente variabile globale
così all'uscita dal for ti ritrovi direttamente i tre valori già assegnati e poi ci fai quello che ti pare
Se vuoi semplificare ulteriormente, elimina quegli R: G: B: all'inizio delle righe, tanto sai già che riceverai tre valori che rappresentano R, G, B e ti risparmi lo split, ti basta convertire in int quello che leggi. In alternativa, puoi usare:
Val(stringa)
che ti restituisce solo la parte numerica quindi
Val("R:23") restituisce 23
Val("B:121") sarà 121
e così proseguendo.
For counter As Integer = 0 To 2
data = SerialPort1.ReadLine()
color(counter) = Val(data)
Next