VB.net and Arduino communication problem

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.

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();
}

    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

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;
}

}

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

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:

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:

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

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).

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.

      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?

PaulS:

      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

      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..

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.

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.

"... 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.

Steen:
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.

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

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.

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.

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

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.

PaulS:

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.

Ok, i see were you are going, and yes that extra string was indeed lazy. Its gone now. My question then is what would be the best way to handle this. I want to send L1 and have the LED turn on. In the future I will be sending a command digit (say M for move) followed by a number that the stepper motor should go to. What would be the best way to accomplish this with the slow serial bus?

Should I receive the first digit, process it, find out its for the LED, then have the arduino wait for the second digit? Again, this first step is about learning how to make it work. I also think it would be best to learn the right way so that I can build good habits early.

Should I receive the first digit, process it, find out its for the LED, then have the arduino wait for the second digit? Again, this first step is about learning how to make it work. I also think it would be best to learn the right way so that I can build good habits early.

The best way, in my opinion, is the use start and end markers. The VB app sends , , , , etc., where < and > are the start and end of packet markers. Then, code like this can read the packet:

#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

Where it says "Process the packet", inData[0] will be the command value, and inData[1] to inData[index] will be the value. Add:

char cmd = inData[0];
inData[0] = ' ';
int val = atoi(inData);

Then, cmd will be what to do and val will be the data ti use with the command.

..."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"...

Not my advise. I will stick to sending orders by sending one byte numbers only (<255) and that's it. You have 255 possibilities. Do you need more than that? No strings that will complicate the reading process and take way longer. Keep it simple! You just need to read one byte and then yes Serial.flush() to clear the buffer and have it ready for the next arriving order (which will be another one byte number). If you don't use Serial.flush() then the next arriving number may not be in the first buffer byte which is what you want to read. You are reading just one byte and you want it to be in the first buffer byte to make it simple. Serial.flush() is a useful instruction the designers provided to be used, not a mistake.

Regarding Serial.println(); please follow my advise and use a simple Serial.write(). No strings, no carriage return, just the number which you will read easily on the computer side.
Again, I have done it this way and works perfectly fine.
Please try this code:

const int DirPin = 3;
const int StepPin = 4;
int a=0;
int b = 0;
int c = 0;
int d = 0;

void setup(){
pinMode(DirPin, OUTPUT);
pinMode(StepPin, OUTPUT);

Serial.begin(9600);

pinMode(8, OUTPUT);

}

void loop() {

if (Serial.available() > 0) {
a=Serial.read();
Serial.flush();
delay(20);
Serial.write(a);
}
if (a ==33) {
digital.Write (8, HIGH);
a=0;
}

if (a == 34) {
digitalWrite (8, LOW);
a=0;
}

}

I guess like the rest of programming their are multiple ways to accomplish the same things. I kind of like the way paul is handling the communications. I it seems like it would be more expandable, when I start sending commands back and forth with information in them.

The being said, I need to learn both ways, since I can see the advantages in it as well.

I have to head out of town for a few days, so will have to work on this when I get back. Also this has given me an idea for another project as well.

Thanks for everyones advice. I was able to get the communication working pretty good, back and forth.

Here is a video of what I have done so far. The vb.net program drives the robot, and the arduino takes care of the interfacing with all the sensors.

Now its onto the dvd writers!