Go Down

Topic: Receive and Display Serial Data in Visual Basic? (Read 18570 times) previous topic - next topic

addy12

hi all,

i got a problem to receive the data from sensor into my visual basic

this is my code for arduino

int trigPin = 3;
int echoPin = 2;

void setup(){
Serial.begin(19200);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}

void loop(){
  int Duration, Distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds (1000);
  digitalWrite(trigPin, LOW);
  Duration = pulseIn(echoPin, HIGH);
  Distance = (Duration/2) / 29.1;
  Serial.print(Distance);
  Serial.println(" cm");
  delay(500);
}

this is my code for visual basic

Imports System.IO
Imports System.IO.Ports
Imports System.Threading

Public Class Form1
    Dim myPort As Array
    Delegate Sub SetTextCallBack(ByVal [text] As String)

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        myPort = IO.Ports.SerialPort.GetPortNames()
        PortComboBox.Items.AddRange(myPort)
        BaudComboBox.Items.Add(9600)
        BaudComboBox.Items.Add(19200)
        BaudComboBox.Items.Add(38400)
        BaudComboBox.Items.Add(57600)
        BaudComboBox.Items.Add(115200)
        ConnectButton.Enabled = True
        DisconnectButton.Enabled = False
    End Sub

    Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        Dim Distance As Integer = SerialPort1.ReadExisting
        SensorTextBox.Text = Distance
    End Sub
End Class


do you know what is the problem here?

AWOL

What happens if you just use the serial monitor instead of the VB?

(please use code tags when posting code)

guix

#2
Jun 19, 2013, 05:29 pm Last Edit: Jun 19, 2013, 05:37 pm by guix Reason: 1
Hello, I think your problem is that:
Quote

The DataReceived event is raised on a secondary thread when data is received from the SerialPort object. Because this event is raised on a secondary thread, and not the main thread, attempting to modify some elements in the main thread, such as UI elements, could raise a threading exception. If it is necessary to modify elements in the main Form or Control, post change requests back using Invoke, which will do the work on the proper thread.


I had a similar problem few days ago, the solution (in C++/CLI) was to use something like this:
Code: [Select]


//in the Form constructor:
this->serialPort1->DataReceived += gcnew SerialDataReceivedEventHandler(this, &Form1::DataReceivedHandler);

...

private: System::Void DataReceivedHandler(Object^ sender, SerialDataReceivedEventArgs^ e)
{
Monitor::Enter(this);

try
{
while (this->serialPort1->BytesToRead > 0)
{
if ( Math::Min(this->serialPort1->BytesToRead, this->serialPort1->ReadBufferSize) > 0)
{
String^ input = this->serialPort1->ReadExisting();
this->textBox2->AppendText( input );
}
}
}

catch ( Exception^ e )
{
this->label1->Text = e->Message;
}

finally
{
Monitor::Exit(this);
}
}


http://msdn.microsoft.com/library/system.io.ports.serialport.datareceived.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2

Not sure if that will help you...

PaulS

Suppose that you put an object in front of the sensor at a distance of 5 cm. You are then sending "5 cm\r\n" to the serial port. You are asking VB to convert that to an int. Is there any real reason to send data that VB needs to discard?

How is VB supposed to know when to stop reading from the serial port? If the Arduino sends "5 cm\r\n 6 cm\r\n" before the VB app gets around to reading it, what do you expect the VB app to show in the text box?
The art of getting good answers lies in asking good questions.

ady88

hi all,

there is no problem if using the serial monitor. i want the vb to display the distance same like appear in serial monitor. so what should i do to display that data? i have tried many code but it still not working

PaulS

Quote
i want the vb to display the distance same like appear in serial monitor.

Then, why are you forcing the text received from the serial port to be converted to an integer?
Why are you expecting the SensorTextBox object's Text property setter to deal with an integer?
Code: [Select]
        Dim Distance As Integer = SerialPort1.ReadExisting
        SensorTextBox.Text = Distance


The Serial Monitor application makes no such demands on the data. It treats all the input as text.
The art of getting good answers lies in asking good questions.

ady88

i am beginner in this thing.so i need to change to another data type.is it?

ady88

hi all,

im have a problem to display my ultrasonic sensor data from Arduino into visual basic. it works if using the serial monitor and i got my data in. but when im trying to display these data on visual basic, im unable to display the sensor data.
this is my code for arduino
Code: [Select]

int trigPin = 8;
int echoPin = 9;

void setup(void)
{
  Serial.begin(19200);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop(void)
{
  if(Serial.available()){
    //Create new variable val
    char val = Serial.read();
   
    if(val != -1)
    {
      switch(val)
      {
      case 'c':
        ultrasonicSensor(); //Print the Sensor data
        break;
      }
  }
}

void ultrasonicSensor()
{
  int Duration, Distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  Duration = pulseIn(echoPin, HIGH);
  Distance = (Duration/2) / 29.1;
  Serial.println(Distance);
  delay(500);
}


and this is the code for Visual Basic
Code: [Select]

Imports System
Imports System.IO.Ports
Imports System.ComponentModel
Imports System.Threading

Public Class Form1
    Dim myPort As Array
    Dim Distance As Integer
    Delegate Sub SetTextCallBack(ByVal [text] As String)

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        myPort = IO.Ports.SerialPort.GetPortNames()
        PortComboBox.Items.AddRange(myPort)
        BaudComboBox.Items.Add(9600)
        BaudComboBox.Items.Add(19200)
        BaudComboBox.Items.Add(38400)
        BaudComboBox.Items.Add(57600)
        BaudComboBox.Items.Add(115200)
        ConnectButton.Enabled = True
        DisconnectButton.Enabled = False

    End Sub

    Private Sub ConnectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ConnectButton.Click
        SerialPort1.PortName = PortComboBox.Text
        SerialPort1.BaudRate = BaudComboBox.Text
        SerialPort1.Open()
        Timer1.Start()

        lblMessage.Text = PortComboBox.Text & " Connected."
        ConnectButton.Enabled = False
        DisconnectButton.Enabled = True
    End Sub

    Private Sub DisconnectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DisconnectButton.Click
        SerialPort1.Close()
        lblMessage.Text = SerialPort1.PortName & " Disconnected."
        DisconnectButton.Enabled = False
        ConnectButton.Enabled = True
    End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Try
            SerialPort1.Write("c")
            System.Threading.Thread.Sleep(250)
            Dim distance As string = SerialPort1.ReadExisting()
            ListBoxSensor.Text = distance
        Catch ex As Exception

        End Try

    End Sub
End Class


is there any error on my code because im unable to display the data into visual basic. please help me.
thanks.

aarondc

Here's the timing for the first time you send C to the Arduino

VB: sends 'c' to the serial port
VB: sleep for 250ms
Arduino: reads serial. if 'c' call ultrasonicSensor
Arduino: writes HI to trigger pin
Arduino: sleeps for 250ms (of 1000ms)
VB: reads serial port and adds result to listbox
Arduino: completes remaining 750ms of 1000ms sleep
Arduino: writes LO to trigger pin
etc

did you try sending the c twice in a row? You may read something in the second time.

aarondc

Ah it's a timer. What is the interval of the timer?

aarondc

And look into asynchronous serial port methods too - synchronous is ugly.

PaulS

Quote
i am beginner in this thing.so i need to change to another data type.is it?

Yes. The same one that the Serial Monitor uses and that the Arduino outputs - String.
The art of getting good answers lies in asking good questions.

ady88

#12
Jul 08, 2013, 06:25 pm Last Edit: Jul 09, 2013, 06:04 am by ady88 Reason: 1
Quote

did you try sending the c twice in a row? You may read something in the second time.


do you mean like this

Code: [Select]

   Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
       Try
           SerialPort1.Write("c")
           SerialPort1.Write("c")
           System.Threading.Thread.Sleep(250)
           Dim i As UShort = SerialPort1.ReadExisting()
           ListBoxSensor.Text = "" + i.ToString()
           Me.Refresh()
       Catch ex As Exception

       End Try


i tried it but still no data displayed. yup, im using timer and the interval is 1000.
im a beginner in vb programming. can you help me fix my code. i have no idea what to do now.

ady88

Quote

The same one that the Serial Monitor uses and that the Arduino outputs - String.


i've changed the data type into string but still no data displayed in textbox. i tried with another way to get the sensor value. i send the "c" character to arduino and arduino print the sensor value.below is the code
Code: [Select]

int trigPin = 8;
int echoPin = 9;

void setup(void)
{
  Serial.begin(19200);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop(void)
{
  if(Serial.available()){
   
    char val = Serial.read();
   
    if(val != -1)
    {
      switch(val)
      {
      case 'c':
        ultrasonicSensor(); //Print the Sensor value
        break;
      }
    }
  }
}

void ultrasonicSensor()
{
  int Duration, Distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  Duration = pulseIn(echoPin, HIGH);
  Distance = (Duration/2) / 29.1;
  Serial.println(Distance);
  delay(500);
}


in visual basic, im using the timer to send the "c" character.below is the code
Code: [Select]

Imports System
Imports System.IO.Ports
Imports System.ComponentModel
Imports System.Threading

Public Class Form1
    Dim myPort As Array
    Dim Distance As Integer
    Delegate Sub SetTextCallBack(ByVal [text] As String)

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        myPort = IO.Ports.SerialPort.GetPortNames()
        PortComboBox.Items.AddRange(myPort)
        BaudComboBox.Items.Add(9600)
        BaudComboBox.Items.Add(19200)
        BaudComboBox.Items.Add(38400)
        BaudComboBox.Items.Add(57600)
        BaudComboBox.Items.Add(115200)
        ConnectButton.Enabled = True
        DisconnectButton.Enabled = False

    End Sub

    Private Sub ConnectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ConnectButton.Click
        SerialPort1.PortName = PortComboBox.Text
        SerialPort1.BaudRate = BaudComboBox.Text
        SerialPort1.Open()
        lblMessage.Text = PortComboBox.Text & " Connected."
        ConnectButton.Enabled = False
        DisconnectButton.Enabled = True
    End Sub

    Private Sub DisconnectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DisconnectButton.Click
        SerialPort1.Close()
        lblMessage.Text = SerialPort1.PortName & " Disconnected."
        DisconnectButton.Enabled = False
        ConnectButton.Enabled = True
    End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Try
            SerialPort1.Write("c")
            System.Threading.Thread.Sleep(250)
            Dim i As String = SerialPort1.ReadExisting()
            ListBoxSensor.Text = i
            Me.Refresh()
        Catch ex As Exception

        End Try

    End Sub
End Class


on timer, i set the interval to 1000. but still not working. whats wrong actually?

thanks for your reply.

PaulS

Code: [Select]
            System.Threading.Thread.Sleep(250)
What it the unit for 250? Is this sleeping for 6+ minutes or 1/4 of a second?

Instead of a timer, use a button with a click event. Step through the code using the debugger.

Instead of something complicated for the Arduino to do (read a ping sensor), make it do something simple:
Code: [Select]
  if(Serial.available())
  {
    char val = Serial.read();
    Serial.print("Hey, Joe!");
  }


Instead of a one letter message to the Arduino, send a bunch of stuff:
Code: [Select]
            SerialPort1.Write("Hey, what a beautiful day. Isn't it great to be alive?")
Then, pay attention to the RX LED on the Arduino. Is it actually receiving anything when you click the button in the VB app?
The art of getting good answers lies in asking good questions.

Go Up