VB.net and Arduino communication problem

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!

Nice; but what I would like to see is how did you do the communication finally. Some code.

Short answer is I used PaulS technique. It may not be the most effecient, but it seemed to get things up and going pretty quickly.

Here is the complete code dump for those that are interested.

//Command Reference
//M = Move to step i.e. M200 moves to step 200
//Z = Zeros the arm to -32000, arm will move up until it hits top
// light sensor
//P = Picks up disk by moving down until sensor on arm is tripped
//S = Displays the status os the sensors
//X = Siliniod Control i.e. X1 turns on the siliniod X0 turns it off

#include <Servo.h>
#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

Servo myservo;

const int headSensor = A1;
const int armSensor = A2;

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

const int silinoidPin = 8;
const int stepDuration = 50;
const int stepDelay = 100;

char inData[80];
byte index;

int currentStep = -32000;

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

Serial.begin(57600);

pinMode(silinoidPin, OUTPUT);

myservo.attach(7); //attaches the servo to pin 7

}

void loop() {
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 Market Arrived. Process the packet
char parrot = inData[0];
inData[0] = ' ';

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

//This is where we decifer the commands coming from the pc
if (cmd == 'M')
{
//Serial.print("Move to: ");
// Serial.println(val);
moveTo(val);
Serial.print("Move Complete to: ");
Serial.print(val);
}
else if (cmd == 'S')
{
readSensor(val);
}
else if (cmd == 'Z')
{
zeroArm();
}
else if (cmd == 'P')
{
pickUpDisk();
}
else if (cmd == 'X')
{
silControl(val);
}
else if (cmd == 'E')
{
pushButton(val);
}

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

Serial.print("<");
Serial.print(parrot);
Serial.print(">");

}

Serial.flush();
}

//This is the function that moves the motor to a chosen point
void moveTo(int val)
{

while(currentStep > val)
{
//The step requested is lower than the current step we are currently on
takeStep(false);
currentStep--;

}
while(currentStep < val)
{
//The step requested is higher than the current step we are currently on
takeStep(true);
currentStep++;
}

}

void pickUpDisk()
{

boolean sensorTriggered = false;
int attemptsMade = 0;

while (sensorTriggered == false)
{
//for safety first we engage the silinoid
digitalWrite(silinoidPin, HIGH);

//we move the arm down until the head sensor makes contact
while (analogRead(headSensor) <800)
{
takeStep(true);
currentStep++;
}

int numberOfSteps = 500; //the number of steps to take after sensor triggered
for (int x = 0; x < numberOfSteps; x++)
{
takeStep(true);
currentStep++;
}
digitalWrite(silinoidPin, LOW);
delay(300);
//now we think we have the disk, we back off numble of steps + 100
//and check the sensor, and try again if the sensor is not triggered
for (int y = 0; y < (numberOfSteps + 200); y++)
{
takeStep(false);
currentStep--;
}

if (analogRead(headSensor) > 800)
{
sensorTriggered = true;
}
//this is here to limit the amount of attempts to 10 tries
if (attemptsMade > 10)
{
Serial.println("Could not Pick Up Disk");
break;
}
else
{
attemptsMade++;
numberOfSteps = (numberOfSteps + 20);
}

}

..."It may not be the most effecient,"...