Buongiorno,
essendo nuovo del mondo arduino ho cercato di imparare la programmazione di arduino. Volevo adesso far comunicare arduino con visul basic express 2013. Per quanto riguarda l'invio dei dati da VB a Arduino non ci sono problemi, anche perchè nelle ricerche effettuate ho trovato abbastanza roba.
Il mio problema è l'opposto, cioè comunicare da arduino a VB. in internet ho trovato qualcosa ma non funziona come vorrei.
Quando premo un pulsante ho un led che si accende, quindi invia sulla seriale la stringa "ACCESO", quando il led è spento invia sulla seriale "SPENTO".
Il problema è quando ricevo le stringhe da arduino in VB in una listbox, la stringa mi viene spezzata a random. non capisco il perchè.
Il codice che ho inserito in VB è il seguente, che sarebbe uguale a un codice trovato in un topic di questo forum.
Private Sub SP1_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
UpdateFormDelegate1 = New UpdateFormDelegate(AddressOf UpdateDisplay)
Dim n As Integer = SP1.BytesToRead 'find number of bytes in buf
comBuffer = New Byte(n - 1) {} 're dimension storage buffer
SP1.Read(comBuffer, 0, n) 'read data from the buffer
Me.Invoke(UpdateFormDelegate1) 'call the delegate
End Sub
Private Sub UpdateDisplay()
' ricevo bytes, se invio 'A' oppure 65, ricevo 65
' chr(65) -> "A"
Dim sBuf As String = "", i As Integer
For i = 0 To comBuffer.Length - 1
sBuf = sBuf & Chr(comBuffer(i))
Next
ListBox1.Items.Add(sBuf)
End Sub
Ho dimenticato di dire che, uso arduino 1. Le stringhe le ricevo correttamente sul monitor seriale, mentre su VB le ricevo tipo questo:
SP
ent
o
Acces
o
Ac
ce
so
Ciao
il codice di arduino per le prove che sto facendo è:
int ledPin = 13;
int ledPin_1=3;
int statoInterruttore=0;
int primaStatoInterruttore=0;
char* myStrings[]={"Spento", "Acceso"};
void setup() {
Serial.begin(9600); // set serial speed
pinMode(ledPin, OUTPUT); // set LED as output
pinMode(ledPin_1, OUTPUT); // set LED as output
pinMode(2, INPUT);
digitalWrite(ledPin, LOW); //turn off LED
digitalWrite(ledPin_1, LOW); //turn off LED
}
void loop(){
if (Serial.available() != 0){
int val=Serial.read()-'0';
if (val == 1) { // test for command 1 then turn on LED
digitalWrite(ledPin, HIGH); // turn on LED
}
else if (val == 0){ // test for command 0 then turn off LED
digitalWrite(ledPin, LOW); // turn off LED
}
}
statoInterruttore=digitalRead(2);
if(primaStatoInterruttore != statoInterruttore){
if(statoInterruttore == LOW){
digitalWrite(ledPin_1, LOW);
Serial.println(myStrings[0]);
}
else if(statoInterruttore == HIGH){
digitalWrite(ledPin_1, HIGH);
Serial.println(myStrings[1]);
}
primaStatoInterruttore = statoInterruttore;
}
}
Posto anche tutto il codice di VB. SP1 è la porta di comunicazione
Imports System.IO.Ports 'Importa la libreria
Public Class Form1
Dim SP1 As New SerialPort
Dim SP1open As Boolean
Dim comBuffer As Byte()
Private Delegate Sub UpdateFormDelegate()
Private UpdateFormDelegate1 As UpdateFormDelegate
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim PortName As String
Dim a() = System.IO.Ports.SerialPort.GetPortNames() ' Dichiarare un Array che si occupa della porte disponibili
SP1.Close()
AddHandler SP1.DataReceived, AddressOf SP1_DataReceived
For Each PortName In a ' un ciclo si occuperà di aggiungere le porte disponibili nella combobox
ComboBox1.Items.Add(PortName) ' Test l'ho scelto io a caso
Next
End Sub
Private Sub BtnSendB_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnSendB.Click
If SP1open Then SP1.Write("0")
End Sub
Private Sub BtnSendA_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnSendA.Click
If SP1open Then SP1.Write("1")
End Sub
Private Sub BtnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpen.Click
With SP1
.BaudRate = 9600
.DataBits = 8
.PortName = ComboBox1.Text '"COM1"
.Parity = IO.Ports.Parity.None
.StopBits = IO.Ports.StopBits.One
.Handshake = IO.Ports.Handshake.None
.Encoding = System.Text.Encoding.Default
End With
Try
SP1.Open()
SP1open = True
Catch ex As Exception
MessageBox.Show(ex.Message)
SP1open = False
End Try
SP1.DiscardInBuffer()
End Sub
Private Sub BtnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClose.Click
SP1.Close()
SP1open = False
End Sub
Private Sub SP1_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
UpdateFormDelegate1 = New UpdateFormDelegate(AddressOf UpdateDisplay)
Dim n As Integer = SP1.BytesToRead 'find number of bytes in buf
comBuffer = New Byte(n - 1) {} 're dimension storage buffer
SP1.Read(comBuffer, 0, n) 'read data from the buffer
Me.Invoke(UpdateFormDelegate1) 'call the delegate
End Sub
Private Sub UpdateDisplay()
' ricevo bytes, se invio 'A' oppure 65, ricevo 65
' chr(65) -> "A"
Dim sBuf As String = "", i As Integer
For i = 0 To comBuffer.Length - 1
sBuf = sBuf & Chr(comBuffer(i))
Next
ListBox1.Items.Add(sBuf)
End Sub
End Class
Ciao nid69ita,
ho visto il link che hai allegato, ma non ho avuto risultati.
Sinceramente conosco poco del codice VB, sono alle prime armi, e la nuova sintassi non so come posso integrarla nel mio progetto, da principiante.
Guarda, io uso ancora VB6 perciò non conosco molto VB.Net, soprattutto la Seriale su Net.
Noto però che nell'esempio di Microsoft usa ReadExisting() mentre tu usi SP1.Read()
Prova a fare così:
Private Sub SP1_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
UpdateFormDelegate1 = New UpdateFormDelegate(AddressOf UpdateDisplay)
Dim indata As String = SP1.ReadExisting()
Console.WriteLine("Data Received:") ' solo per debug
Console.Write(indata) ' solo per debug
comBuffer = indata
Me.Invoke(UpdateFormDelegate1) 'call the delegate
End Sub
Fai diventare comBuffer di tipo String e nella UpdateFormDelegate1 usa direttamente comBuffer e non sBuf.
In questo modo non devi più passare da un vettore/array di byte
ho provato a dichiarare Dim comBuffer As String e ho scritto il codice come segue:
Private Sub SP1_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
UpdateFormDelegate1 = New UpdateFormDelegate(AddressOf UpdateDisplay)
Dim indata As String = SP1.ReadExisting()
Console.WriteLine("Data Received:") ' solo per debug
Console.Write(indata) ' solo per debug
comBuffer = indata
Me.Invoke(UpdateFormDelegate1) 'call the delegate
End Sub
Private Sub UpdateDisplay()
' ricevo bytes, se invio 'A' oppure 65, ricevo 65
' chr(65) -> "A"
Dim sBuf As String = "", i As Integer
For i = 0 To comBuffer.Length - 1
sBuf = sBuf & Chr(AscW(comBuffer(i)))
Next
ListBox1.Items.Add(sBuf)
End Sub
non ho errori, gira, ma ho sempre lo stesso problema, cioe:
SP
ent
o
Acces
o
Ac
ce
so
non capisco come fare a far capire a VB quanto è lunga la stringa che c'è nella seriale, oppure non so se arduino è lento a scrivere, quindi VB vede più stringhe.
' ricevo bytes, se invio 'A' oppure 65, ricevo 65
' chr(65) -> "A"
Dim sBuf As String = "", i As Integer
For i = 0 To comBuffer.Length - 1
sBuf = sBuf & Chr(AscW(comBuffer(i)))
Next
ListBox1.Items.Add(sBuf)
End Sub
Ripeto, sBuf non serve più.
Private Sub UpdateDisplay()
ListBox1.Items.Add(comBuffer)
End Sub
si scusa avevo dimenticato di scriverlo. Ho provato in tutti e due i casi anche usando sBuf, ma il risultato è uguale.
non so se c'è un modo per far inviare una stringa da arduino con un carattere speciale. Quando VB legge questo carattere significa che la stringa è terminata.
Se qualcuno sa come si fa, credo che possa andare bene.
Purtroppo si. In pratica tra il codice che avevo postato all'inizio e quest'ultimo codice, con le varie modifiche, non c'è differenza nel risultato.
Ho sempre le stringhe slittate a caso. Tipo:
SP
ent
o
Acces
o
Ac
ce
so