Go Down

Topic: VB.net and Arduino communication problem (Read 3 times) previous topic - next topic

CaptRR

I think I may have been looking at this thing too long and might be ignoring something obvious.

Here is what the code below does.  I have it set so when I type in a number in a text box, it sends that number to the arduino.  It then parrots that number back at me.  If that number is 33 it turns the led on, if its 34, it turns the led off.

Whats happening, is that while the led seems t control fine, the data I am getting parroted back to me is odd.  The first time I type something and hit send, my message box comes up, and displays 34 3 (if I typed in 45 it would show 45 3, 22 would show 22 3, ect).  The second time I put in any number the message box show 0 0.

The code is mainly just a way for me to figure out how communication works, but at this point I am stumped.

Quote



const int DirPin = 3;
const int StepPin = 4;

int a = 0;
int b = 0;
int c = 0;
int d = 0;
int val = 0;


void setup(){
  pinMode(DirPin, OUTPUT);
  pinMode(StepPin, OUTPUT);
  
  Serial.begin(9600);
  
  pinMode(8, OUTPUT);
  
}

void loop() {
  if (Serial.available() > 0) {
    
    
    a = Serial.read();

    
    val = a;
    
    Serial.println(val);
    
    if (val == 33) {
      digitalWrite (8, HIGH);
    }
    
    if (val == 34) {
      
      digitalWrite (8, LOW);
      
    }
 //   if (val == 5001){
 //     digitalWrite (8, HIGH);     
 //   }
    
 //   if (val == 5002){
 //     digitalWrite (8, LOW);
 //   }
    
  
    
  }
  
  Serial.flush();
}







Code: [Select]

    Dim TestVar As String

    Private Sub sendDataBtn_Click(sender As System.Object, e As System.EventArgs) Handles sendDataBtn.Click
        TestVar = goToStepTextBox.Text

        Dim btyeArr() As Byte = BitConverter.GetBytes(CInt(goToStepTextBox.Text))




        If Not SerialPort1.IsOpen Then
            SerialPort1.Open()
        End If

        SerialPort1.Write(btyeArr, 0, btyeArr.Length)



        'SerialPort1.Close()
    End Sub

    Private Sub SerialPort1_DataReceived(sender As Object, e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        Dim recStr As String = ""

        Dim Datareceived As Boolean

        Datareceived = False

        While Not Datareceived

            Dim recVal As Integer
            recVal = SerialPort1.ReadByte()
            If recVal = 10 Or recVal = 13 Then
                Datareceived = True
            Else
                recStr = recStr + Chr(recVal)

            End If
        End While

        MessageBox.Show(recStr & " " & CChar(recStr))


    End Sub
End Class

arduinoadrian

Try this:

I think Serial.println(); is your problem as it writes also carriage return and I don't know what else to the port. Try Serial.write();

void loop() {
  if (Serial.available() > 0)

{     
    a = Serial.read();    //No need to use (val).
    Serial.flush();         //Clears the buffer after reading it to have it ready for the next arriving number.
    Serial.write(a);      //Writes the number back to the port.
}   
    if (a == 33)
    {
      digitalWrite (8, HIGH);
      a=0;                    //Clears a once its used to have it ready for the next arriving value.
    }
   
    if (a == 34)
    {     
      digitalWrite (8, LOW);
      a=0;     
    }   
 
}
Perseverance is 90% of the solution. The remaining 10% is more perseverance.

Steen

#2
Apr 13, 2012, 06:50 pm Last Edit: Apr 13, 2012, 07:04 pm by Steen Reason: 1
The problem is in the conversion of your textbox i think. I tried it with the serial monitor and sent 33 to it (which gets sent as 3 and 3 not 33, but whatever) and it returns what it should return. So that means the sent string/byte from the pc is wrong.
I built the program you gave and put a messagebox that shows which byte it sends when pushing the button, and it sends "!", which is 33 and quote char, which is 34, so that works.. so now there's the strange thing, where's the mistake. I tried to find it, but did not succeed..

i'll try again, and if i find something i'll tell you.

edit: serial.flush() does NOT clear the buffer, it waits for every byte to be sent in the new arduino IDE
@arduinoadrian: i wrote that VB code myself (and i like it to see it appearing here), and i know everything works with the receiving part if you use println(), so that's not our problem

Steen

I solved it in a way it isn't really solved, but you don't see it anymore.. if that's enough for you xs although i would lik eto see it really solved, here's the code:
Code: [Select]

int a = 0;

void setup(){
 
  Serial.begin(19200);
 
  pinMode(8, OUTPUT);
 
}

void loop() {
  if (Serial.available() > 1) {
   
    a = Serial.read();
    if (a > 0){
     
      Serial.println(a);
     
      if (a == 33) {
        digitalWrite (8, HIGH);
      }
     
      if (a == 34) {
        digitalWrite (8, LOW);
      }
     
    }
   
  }
 
}


VB:
Code: [Select]

Imports System.IO.Ports

Public Class Form1
    Dim TestVar As String

    Private Sub sendDataBtn_Click(sender As System.Object, e As System.EventArgs) Handles sendDataBtn.Click
        TestVar = goToStepTextBox.Text

        Dim btyeArr() As Byte = BitConverter.GetBytes(CInt(goToStepTextBox.Text))

        SerialPort1.Write(btyeArr, 0, btyeArr.Length)

    End Sub

    Private Sub SerialPort1_DataReceived(sender As Object, e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        Dim recStr As String = ""

        Dim Datareceived As Boolean

        Datareceived = False

        While Not Datareceived

            Dim recVal As Integer
            recVal = SerialPort1.ReadByte()
            If recVal = 10 Or recVal = 13 Then
                Datareceived = True
            Else
                recStr = recStr + Chr(recVal)
            End If
        End While

        'MessageBox.Show(recStr & " " & CChar(recStr))

        If recStr.Length >= 1 And recStr <> "255" Then
            MsgBox(recStr)
        End If

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        With SerialPort1
            .Close()
            .PortName = "COM3"
            .BaudRate = 19200
            .Parity = Parity.None
            .DataBits = 8
            .StopBits = StopBits.One
            .ReceivedBytesThreshold = 1
            .Open()
        End With
    End Sub
End Class

arduinoadrian

I know it should work with Serial.println(), its just more complicated than using Serial.write() which I have used hundreds of times flawlessly. If you want to make it simple and extremely effective I recommend you use Serial.write(). One byte at a time and that's it. I have done it.

On the computer side using Processing its extremely simple and effective also with just this:

if(port.available()>1)
{value=port.read()
port.clear()}      //you need to clear the port once its read to have it ready for the next value to be received.

On the Arduino side;

Serial.flush(); does indeed clears the buffer once it is executed. At least for my Project it does. I'm sending several orders to Arduino one after another that are read within the same loop and it reads them flawlessly. That means it is clearing the buffer indeed, otherwiwe there will be different results and it is working perfectly. I just gave it a little delay between sending values and another delay on the Arduino side in between readings to guarantee the values are there when I need them in the same loop. I have no question about Serial.flush(); at least with what I'm using. I downloaded the Arduino IDE maybe 5 moths ago and using Duemilanove. This is such an important instruction that I don't see why they would have changed its operation the way you are mentioning. Here there is just one byte wrttten with each write command. I don't see why it will wait until anither command to flush the buffer. One command read and it ends right there does no have to wait for any other byte on the same command. Maybe for multy byte numbers it works the way you say; but definetley not for one byte which is what is being used here (number<255).

Perseverance is 90% of the solution. The remaining 10% is more perseverance.

arduinoadrian

Sorry, it should have been:

if(port.available()>0)
{value=port.read();
port.clear();}      //you need to clear the port once its read to have it ready for the next value to be received.

Perseverance is 90% of the solution. The remaining 10% is more perseverance.

PaulS

Code: [Select]
      if (a == 33) {
        digitalWrite (8, HIGH);
      }
     
      if (a == 34) {
        digitalWrite (8, LOW);
      }

Why do you want to go look at the ASCII table every time you add a value being sent?

After looking at the ASCII table for the values 33 and 34, I guess my real question is what the f**k?

Why not send something sensible, instead?

Steen


Code: [Select]
      if (a == 33) {
        digitalWrite (8, HIGH);
      }
     
      if (a == 34) {
        digitalWrite (8, LOW);
      }

Why do you want to go look at the ASCII table every time you add a value being sent?

After looking at the ASCII table for the values 33 and 34, I guess my real question is what the f**k?

Why not send something sensible, instead?


if he would be looking at the asccii table, he would do
Code: [Select]
      if (a == '!') {
        digitalWrite (8, HIGH);
      }
     
      if (a == '"') {
        digitalWrite (8, LOW);
      }


wouldn't he? here he just reads the values back, which are numbers.. i understand that it would be easier to send something you can understand, such as L1 or L0 (from led on and led off) but that's his choice..

PaulS

Quote
if he would be looking at the asccii table, he would do...wouldn't he?

Yes. It was the odd values in the ASCII table that caused to go hmmm.

Quote
i understand that it would be easier to send something you can understand, such as L1 or L0 (from led on and led off) but that's his choice..

Or N and F, A and B, whatever, to make it easy to know what to send. 33 and 34 just do not make sense.

arduinoadrian

"... i understand that it would be easier to send something you can understand, such as L1 or L0 (from led on and led off) but that's his choice.."

Exactly, that's his choice and as long as it makes sense for him and works fine, that's OK. Writting code is part science and part art. Maybe he just likes these numbers 33 and 34 to be sent.

"...After looking at the ASCII table for the values 33 and 34, I guess my real question is what the f**k?..."

There are nicer ways of suggesting a solution to help.
Perseverance is 90% of the solution. The remaining 10% is more perseverance.

CaptRR



wouldn't he? here he just reads the values back, which are numbers.. i understand that it would be easier to send something you can understand, such as L1 or L0 (from led on and led off) but that's his choice..



Thanks for everyone's response, I am going to work on this some more today.  As I said before I am learning and this was mainly an example.  If something like L1 is the best practice, then I will definitely do it in the future.

I guess I should probably explain what my end goal is.  About 2 years ago, someone threw away a nice cd changing robot.  One with the printer, grabber, ect.  After tearing into it, I noticed the only really bad was the control board, which I figure can be replaced by an arduino.  I have already made the arm move where i want to with the stepper, and got all the sensors working, got the printer working last year.  Now I need to tackle the communication with the computer.

Basically I imagine most of the commands coming from the computer (i.e. go to step 100, release grabber arm)  With the arduino sending events back to the computer when something happens (i.e. movement completed or sensor triggered movement stopped)  That sort of thing.  So I should be able to keep my commands pretty simple.

Maybe use the first byte for commands, and the rest can be numbers?

Once again thanks for everyone's help.




Steen

wow, nice รถ and everything works, that's great!

well, you should do it the way you want it, but it is best to have a short string (one char) that gets sent before the number because the you know yourself what command handles which instruction.
Like when you want to move the stepper arm, you can do S100 to move the stepper arm to 100. Then analyse this with the arduino, and that's it

arduinoadrian

Interesting project. The good thing with any project is that one learns many things that can be used in next projects and they will be easier to tackle.
Keep going and if you need more help post here and we will be willing to help with what we know.

I try to follow these guide lines whenever possible:

-Keep it simple. The less code and hardware the better.
-Use explicative variable names, so it will be easier to understand.

Good luck.
Perseverance is 90% of the solution. The remaining 10% is more perseverance.

CaptRR

Taking everyone's advice I decided to change things.  Got rid of the numbers and instead went with L0 and L1 like was mentioned above.  Also forgetting about the visual basic stuff for now, just going to get the arduino working through the serial monitor then write the vb program.

Here is the changed code.
Quote



const int DirPin = 3;
const int StepPin = 4;

String a= "";
int b = 0;
int c = 0;
int d = 0;
String val = 0;


void setup(){
  pinMode(DirPin, OUTPUT);
  pinMode(StepPin, OUTPUT);
  
  Serial.begin(9600);
  
  pinMode(8, OUTPUT);
  
}

void loop() {

 
  if (Serial.available() > 0) {
    
    while (Serial.available() > 0) {
    
      //a = a + char(Serial.read());
      a.concat(char(Serial.read()));
      
      
      

    }
    

     Serial.println(a);
    
    if (a == "L1") {
      digitalWrite (8, HIGH);
    }
    
    if (a == "L0") {
      
      digitalWrite (8, LOW);
      
    }
  }
  a = "";
  Serial.flush();
}





When using the serial monitor I seem to have extra carriage returns however, and the LED does not seem to turn on.  So it seems that the carriage return is getting written into the a string.  I just can't figure out where.

When I type L1 into the serial monitor I get:
L
1

When I type L2 I get:
L
2

When I type L11 I get:
L
1
1

Finally When I type L1111 I get:
L
1
1
11

Odd

PaulS

Code: [Select]
String a= "";
String val = 0;

You have a limited amount of memory on the Arduino. Using a String object to receive a 2 character input is the ultimate in laziness.

Your problem is a unrealistic expectation about how serial data is transmitted. The key to understanding serial data transmission is to understand that it is sssslllloooowwww.

You are expecting the serial data to arrive all at once. It does not. There may be a thousand iterations of loop between the time the L arrives and the time that the 1 arrives, when you enter L1 and press Send.

Serial.flush() is almost certainly a mistake. Unless you KNOW what it is doing, and have very good reason to have it there, get rid of it.

Go Up