Go Down

Topic: Interaction with Visual Basic 2010 (Read 1 time) previous topic - next topic

piraky

I am trying to control stepper motors from visual basic 2010.

I am having trouble either reading the number of bytes, or setting the delay time on arduino.
On VB,
Code: [Select]

Dim message As String = "11"
If drawing Then
         Dim j As Integer
          For j = 1 To Len(message)
                Printer.Write(message)
          Next j
          Threading.Thread.Sleep(2000)
End If


Arduino->
Code: [Select]
void loop()
{
    if(Serial.available()>0){
      steps=0;
      while(Serial.available()>0){
        incomingbyte=Serial.read();
        *tmp=incomingbyte;
        int digit=atoi(tmp);
        if(steps!=0){
          steps=steps*10;
        }
        steps=steps+digit;
      }
     
     Serial.write(steps);
     motor1.step(steps,FORWARD,SINGLE);
     delay(10);
     
    }
}

 

When the message is one byte, "1" to "9" it works perfectly.
When "10" is sent, the motors moves a lot more than 10.
For self-feedback, Serial.write(steps) returns the desired value, but when 10 is sent out from VB, i get back 10, 1, 10, 1....
When 11 is sent, i get back 111, 1, 111, 1...

I am not sure where or how it went wrong. Please help me.

thank you!

Graynomad

You're only reading a single byte then the while loop will exit because it's done the work before the next char arrived.

Try something like

Code: [Select]
    if(Serial.available()>= 2){
      steps=0;
        *tmp++ = Serial.read();
        *tmp++ = Serial.read();
        *tmp = '\0';
        int digit=atoi(tmp);
        if(steps!=0){
          steps=steps*10;
        }
        steps=steps+digit;
      }


______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

piraky

I tried to add delay in the while loop but the code didn't work well.
Sometimes more than 3 bytes will be sent so I don't want to restrict to Serial.available() >= number..

Thank you!

Graynomad

Quote
Sometimes more than 3 bytes will be sent

How many?

If we're just looking and a number then send it in binary so the number of characters is always the same.

OR

Continue sending as ASCII but 0 fill, ie "023" instead of "23" then you know how many chars you will get,

OR

Send a delimiter so you know when the data has finished.

Also I just noticed

Code: [Select]
         For j = 1 To Len(message)
               Printer.Write(message)
         Next j


This will send the string twice. The longer the string the more times it gates sent.

______
Rob

Rob Gray aka the GRAYnomad www.robgray.com

piraky

At first, I just had Printer.Write(message), but it only sent the first digit of the message. I thought that was weird, but it just didn't work without the loop.

From the code you gave me, I modified it so that it fits in all cases
Code: [Select]
data=Serial.available();
      if (data>0){
          int i;
        for(i=0;i<data;i++){
        *tmp++=Serial.read();
        }
        *tmp='\0';
        steps=atoi(tmp);
      }
     Serial.write(steps);
     motor1.step(steps,FORWARD,SINGLE);
     delay(10);


This didn't work, so I just added your code with the original one
Code: [Select]
  steps=0;
    if(Serial.available()>1){
        *tmp++=Serial.read();
        *tmp++=Serial.read();
        *tmp='\0';
        steps=atoi(tmp);
      }
    else if(Serial.available()>0){
      while(Serial.available()>0){
        incomingbyte=Serial.read();
        *tmp=incomingbyte;
        steps=atoi(tmp);
        //delay(100);
      }
    }


and it works for one digit. it works for 2 digit ONCE (sometimes).
I began to think something is wrong with the motor...?

Graynomad

#5
Mar 25, 2011, 04:48 pm Last Edit: Mar 25, 2011, 06:29 pm by Graynomad Reason: 1
The modified code does not fit all cases, because the Arduino is 10,000 times faster than the serial line it does the entire loop for every character it receives. That's why you either have to wait for N characters to arrive (and know when there is an idle line) OR have a delimiter.

Also how do you know when a new batch of data starts? Lets say VB is sending three characters at 2sec intervals

Code: [Select]
123-----------------------234-------------------456--------------------567
                          ^


and you start reading the serial port at the ^ position.

You will read 344.

Now if VB sends "<123>", Arduino ignores all characters until it sees < and reads until > then you both have a method to sync on the data and know when a packet ends.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

piraky

Rob, thank you so much for helping me.
I understand more about the functionality of serial port more each time you give me a reply :)

I was hoping thread.sleep(2000) will give enough time for arduino to move the motor and listen to the next lines of bytes sent through, but I guess it doesn't stack up...
I added <> in VB to send though the message. < is 60 and > is 62 for ascii
Code: [Select]
steps=0;
  if(Serial.available()>0){
    if(Serial.read()==60){
      incomingbyte=Serial.read();
      while(incomingbyte<58){
        Serial.write(incomingbyte);
        *tmp++=incomingbyte;
        incomingbyte=Serial.read();
      }
    }
  }
  *tmp='\0';
  steps=atoi(tmp);
  motor1.step(steps,FORWARD,SINGLE);


I had it while(incomingbyte!=62) but it didn't work, so I changed it to less than 58.
The motor is not working and I am getting 63(? for ascii) for Serial.write().

Adding Serial.flush() was no help...
What am I doing wrong this time?

Thank you!

wildbill

You're still reading and using serial data when you don't really know that you have any.

Try this:
Code: [Select]

steps=0;
if(Serial.available()>0 && Serial.read()=='<')
  {
  incomingbyte=0;
  do
    {
    if(Serial.available()>0)
      {
      incomingbyte=Serial.read();
      Serial.write(incomingbyte);
      *tmp++=incomingbyte;     
      }
    }
  while(incomingbyte != '>');
  }
  *tmp='\0';
  steps=atoi(tmp);
  motor1.step(steps,FORWARD,SINGLE);


Note that the string you end up with that tmp points to will have a '>' on the end of it. Atoi won't care, just make sure your buffer is big enough. Alternatively, write the terminating zero on it.

piraky

Hi again,

I copied and pasted it but it still doesn't work. I sent "<10>", and it gives me 49 and 48 (1 and 0) and then visual basic freezes. I put serial.write right after while, and not getting anything so I am assuming it is in the while loop and not getting out of it.

why?

piraky

Finally worked... To be honest, I don't know why the others didn't work.

Here's the code
Code: [Select]
  if(Serial.available()>0){
    data=Serial.read();
    if(data=='<'){
      *tmp=Serial.read();
      steps=atoi(tmp);
    }
    else if(data=='>'){
      Serial.write(steps);
      motor1.step(steps,FORWARD,SINGLE);
      steps=0;
    }
    else{
      *tmp=data;
       steps=10*steps;
       steps=steps+atoi(tmp);
    }
  }


Thank you so much!

Go Up