Pages: [1]   Go Down
Author Topic: Robot control over COM  (Read 694 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 4
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I want to control my robot over com port according this scheme: If I sent ";1;1;1;1;"-all motor are switched on. If I sent ";0;0;0;0;"-all motors are switched off. If I sent ";0;1;0;1;" second and fourth motors are switched on, first and third are switched off. Each motor is controled by his own optocoupler, but now I have had connected LEDs instead them. I would like to pres for exaple DOWN and RIGHT and it should sent  ";0;1;0;1;" in loop, but when i do not press anything it should sent ";0;0;0;0;" and so forth. The codes does not work properly, for exaple it is imposible to have 2 LEDs switched on together or when I release a key it sometimes still shines. I think, that a mistake is in processing code. I was trying almost everything and I am desperate.
Sorry for my crappy English.
Here is the processing code:
Code:
int forward;
int backward;
int left;
int right;
import processing.serial.*;
Serial myPort;  // Create object from Serial class
void setup()
{
  size(640,480);
  // I know that the first port in the serial list on my mac
  // is always my  FTDI adaptor, so I open Serial.list()[0].
  // On Windows machines, this generally opens COM1.
  // Open whatever port is the one you're using.
  String portName = Serial.list()[1];
  myPort = new Serial(this, portName, 9600);
}
void draw() { } // Empty draw() needed to keep the program running


void keyPressed() {
  if (key == CODED) {
    if (keyCode == UP) {
      forward = 1;
    }  
    if (keyCode == DOWN) {
      backward = 1;
    }
   if (keyCode == LEFT) {
      left = 1;
    }  
    if (keyCode == RIGHT) {
      right = 1;
    }
  }
  delay(10);
  myPort.write(";"+forward+";"+backward+";"+left+";"+right+";");
}
void keyReleased() {
  if (key == CODED) {
    if (keyCode == UP) {
      forward = 0;
    }
    
  
    if (keyCode == DOWN) {
      backward = 0;
    }
    
  
   if (keyCode == LEFT) {
      left = 0;
    }
  
  
    if (keyCode == RIGHT) {
      right = 0;
    }
  }
  
   myPort.write(";"+forward+";"+backward+";"+left+";"+right+";");
}

here is the arduino code:
Code:
int forwPin=13;
int backPin=10;
int leftPin=11;
int rightPin=12;
String readString = String("");
String forward;
String backward;
String left;
String right;
void setup() {
  // initialize serial communication:
  Serial.begin(9600);
   // initialize the LED pins:
      
        pinMode(forwPin, OUTPUT);
        pinMode(backPin, OUTPUT);
        pinMode(leftPin, OUTPUT);
        pinMode(rightPin, OUTPUT);
      }


void loop() {

        while (Serial.available()) {
        delay(10);  
          if (Serial.available() >0) {
        char c = Serial.read();  //gets one byte from serial buffer
        readString += c;} //makes the string readString
        }
        
      while (readString.length() >0) {
        forward=readString.substring(1,2);
        backward=readString.substring(3,4);
        left=readString.substring(5,6);
        right=readString.substring(7,8);
         Serial.println("F"+forward+"B"+backward+"L"+left+"R"+right);
        
      
      if (forward == '1') {
          digitalWrite (forwPin,HIGH);
            Serial.println( "OK");
      }
            else digitalWrite (forwPin, LOW);
    
        if (backward == '1') {
          digitalWrite (backPin,HIGH);
            Serial.println( "OK");
        }
            else digitalWrite (backPin, LOW);
        
        if (left == '1') {
          digitalWrite (leftPin,HIGH);
            Serial.println( "OK");
        }
            else digitalWrite (leftPin, LOW);
        
        if (right == '1') {
          digitalWrite (rightPin,HIGH);
            Serial.println( "OK");
        }
            else digitalWrite (rightPin, LOW);
      
      readString="";  
      }
       //;F;B;L;R;  

   }
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 652
Posts: 50869
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
       while (Serial.available()) {
        delay(10);
          if (Serial.available() >0) {
You have a while loop that will only be executed if there is serial data to be read. How can the if test then ever result in any value but true?

Code:
     while (readString.length() >0) {
This call is inside the while loop for serial data being available to read. So, you are going to use the serial data before all the serial data has been read. Is that a good idea?

Code:
       forward=readString.substring(1,2);
        backward=readString.substring(3,4);
        left=readString.substring(5,6);
        right=readString.substring(7,8);
If you've read 3 characters, extract substrings based on all 8 of them. Do you see a problem with this?

Code:
     if (forward == '1') {
On one side of the == operator, you have a String. On the other side, you have a character. They will NEVER be equal.

The == in this case is not part of the String class. You want, I believe, to be using forward.equals(), rather than ==, and "1", not '1'.

Also, the substring will be ";1", not "1", so you'll want to take this into account, too.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 4
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for advice, but it still doesn't work.
I restructured it according your advices, but if I press a key for too short or too long time, it starts to glow, but it won't stop till I press another key. "If you've read 3 characters, extract substrings based on all 8 of them. Do you see a problem with this?" No ,I don't. I will always send characters in group of 9 of them. "Also, the substring will be ";1", not "1" That's not true, try it.

Code:
int forwPin=13;
int backPin=10;
int leftPin=11;
int rightPin=12;
String readString = String("");
String forward;
String backward;
String left;
String right;
void setup() {
  // initialize serial communication:
  Serial.begin(9600);
   // initialize the LED pins:
      
        pinMode(forwPin, OUTPUT);
        pinMode(backPin, OUTPUT);
        pinMode(leftPin, OUTPUT);
        pinMode(rightPin, OUTPUT);
      }


void loop() {

        while (Serial.available()) {
        delay(10);  
        char c = Serial.read();  //gets one byte from serial buffer
        readString += c; //makes the string readString
        }

        
      while (readString.length() >0) {
        forward=readString.substring(1,2);
        backward=readString.substring(3,4);
        left=readString.substring(5,6);
        right=readString.substring(7,8);
         Serial.println("F"+forward+"B"+backward+"L"+left+"R"+right);
          readString="";  
      }
      
      if (forward.equals(1)) {
          digitalWrite (forwPin,HIGH);
            
      }
            else digitalWrite (forwPin, LOW);
    
        if (backward.equals(1)) {
          digitalWrite (backPin,HIGH);
            
        }
            else digitalWrite (backPin, LOW);
        
        if (left.equals(1)) {
          digitalWrite (leftPin,HIGH);
            
        }
            else digitalWrite (leftPin, LOW);
        
        if (right.equals(1)) {
          digitalWrite (rightPin,HIGH);
          
        }
            else digitalWrite (rightPin, LOW);
      
    
      
       //;F;B;L;R;
        


      

   }
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 652
Posts: 50869
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Serial data transmission is slow. The Arduino is fast. It takes far longer to transmit the data than it takes the Arduino to read it. The Arduino begins reading as soon as the first character arrives.

In your while loop, you see that there is a character to read. You read it. Then, you try to process all 9 characters. Then, you read another character. That's 2. Then, you try to process all 9 again. Then, you read another character. That's 3. Then, you try to process all 9 again.

You need to read all 9 characters before trying to process any of them.

You also need to handle the loss of a character. You need to have start and end of packet characters that are distinct from any characters in the packet. If you see a start of packet marker without having see the previous end of packet marker, you know that there was data loss, and that you should discard the packet.

If you see a end of packet marker, without having seen the corresponding start of packet marker, you know that there was data loss, and that you should discard the packet.

If you see a start of packet marker and end of packet marker, in the correct order, but the expected number of characters in between is incorrect (i.e. is not 7), you know that there was data loss, and that you should discard the packet.

If you see the start of packet marker and end of packet marker in the corect order, with the correct number of characters in between, then you can assume that the packet is complete (not necessarily good, just complete), and can attempt to parse it.

Quote
"Also, the substring will be ";1", not "1" That's not true, try it.
Right. The substring isn't ";1", it is be "1;".

The revised code is better, but it still needs some work to be more robust. It also still has some problems.

Quote
Syntax

string.equals(string2)
Code:
     if (forward.equals(1)) {
So, forward is a string. It's equals function is called. The argument to the equals() function is 1. There is no way that you can convince me that 1 is a string.

The call should be:
Code:
     if (forward.equals("1;")) {
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 92
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

PaulS is correct.  The serial data transmission occurs at 9600 bits per second.  The Arduino operates at 16 Mhz.  (That's 16,000,000 cycles per second.)  It's very likely that the Arduino will process many commands (1,666) between each character that is received.

You may want to limit your while loop to only execute when there's enough data in the buffer to do something with it.  

while (Serial.available() >= smiley-cool
{
...
}

Better yet, use an interrupt so you don't waste cycles polling the buffer.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 652
Posts: 50869
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Better yet, use an interrupt so you don't waste cycles polling the buffer.
Would you please elaborate on this topic? How would you use an interrupt that was triggered by the arrival of the 8th byte on the serial port?

The best solution is to read the serial data that is ready to be read on each pass through loop. When the end of packet is detected (hopefully because the sender is including a specific end-of-packet marker, otherwise when 8 bytes have been read), then do something with the serial data, but only then.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 92
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you assume the packet size is 8 bytes, there is no reason to look for an end-of-packet marker if there isn't enough data in the buffer to contain a complete packet.

So, if you enable an interrupt which triggers at the same rate as the baud rate of the serial connection, then you won't be wasting CPU cycles polling the Serial.available().  It will only ask if it's even possible that a new byte had arrived.  

Remember that baud rate = bits per second, not bytes per second.  So 9600 baud really is 1200 bytes/sec.  Serial communication only ocurs at the byte level.  You must send 8 bits, you cannot just send 1 bit at a time.

Since you know that it will take at least (1200 Bytes/sec) * (1 packet / 8 bytes) cycles to receive an entire packet, set the interrupt to fire at that rate.  (ie: 150 times a sec)

Below is some pseudocode to illustrate:

//Fire the Interrupt Service Routine 150 times per second (ie: 1200 / smiley-cool
ISR()
{
if (Serial.available() >= smiley-cool
{

//Grab the packet from the buffer
//and parse the command.
while (received != endofpacket)
{
receive = Serial.read();
}

}//End If
}//End ISR
« Last Edit: October 28, 2010, 12:35:41 pm by BKnight760 » Logged

Pages: [1]   Go Up
Jump to: