Go Down

Topic: Arduino reading serial data too quickly? (Read 3591 times) previous topic - next topic

sinkoman

Mar 15, 2012, 05:32 am Last Edit: Mar 15, 2012, 05:36 am by sinkoman Reason: 1
Hey guys, i've got a pretty simple problem here. What I have is a program which reads commands from the serial port, then moves a stepper motor based on what it receives.

It seems to work pretty well, but if you'll notice, i've got a short 10ms delay at the beginning of my code (marked with two question marks). If I remove this delay, the code will work fine in the arduino serial monitor, but if I try to use br@y's terminal to send commands, I wind up with all sorts of random symbols in between bytes, I assume because the arduino is reading bytes faster than the terminal can supply them.

The delay seems to work well enough, but it kinda seems like a poor way of doing things, as it's currently set to an arbitrary value.

I guess my question is, what am I doing incorrectly in my code to incite this discrepancy?

Code: [Select]
/**
**/

#include <Stepper.h>

const String errorMsg = "invalid command";

const int rev = 200; // #of steps in one revolution of the motor
const int deviceNum = 1; //this is the number of the arduino in mark's prog
const int homeSwitch = 8; //pin # for home position limit switch
const int motorPin[] = {13, 12, 11, 10};
const float mmPerStep = .0508;

//commands
const String stopCmd = "ST";
const String posAbsCmd = "PA";
const String homeCmd = "MO";
const String currentPosCmd = "CP";

Stepper stepper(rev, motorPin[0], motorPin[1], motorPin[2], motorPin[3]);

//storage variables
char inByte;
String inString;
int head;
String cmd;
String foot;
int strPointer;
boolean isGood;
float cmdVal;

int currentPos;

void setup(){
 Serial.begin(57600);
 pinMode(homeSwitch, OUTPUT);
 stepper.setSpeed(60); //speed of the motor in RPM
//  establishContact();
}

void loop(){
 
 if(Serial.available() > 0){
   
   while(Serial.peek() != 13 && Serial.peek() != 10){      
     inByte = Serial.read(); //recieve bytes
     
//      Serial.print("inByte ");
//      Serial.println(inByte);
     
     inString += inByte; //arrange into a string
     delay(10); //???
   }
   
//    Serial.print("inString ");
//    Serial.println(inString);
   
   if((inString.charAt(0) >= 48) && (inString.charAt(0) <= 57)){ //if the first character is a number    
     
     for(int i = 0; (inString.charAt(i) >= 48) && (inString.charAt(i) <= 57); i++){ //until a non 0-9 character is encountered
       head = head * 10 + (inString.charAt(i) - '0'); //add the character to the head var
       strPointer = i;
     }
     
     if(head == deviceNum){ //if they're talking to us
       
       strPointer++;
       
       for(int i = strPointer; i < inString.length(); i++){
         if(!((inString.charAt(i) >= 48) && (inString.charAt(i) <= 57) || (inString.charAt(i) == 46))){
           cmd += inString.charAt(i);
         } else {
           break;
         }
           strPointer = i;
       }
       
//        Serial.print("cmd ");
//        Serial.println(cmd);
       
       if(cmd == "PA"){
         //Position Absolute
         
         isGood = true;
         
         for(int i = strPointer + 1; i < inString.length(); i++){
           if(!((inString.charAt(i) >= 48) && (inString.charAt(i) <= 57) || (inString.charAt(i) == 46))){
             isGood = false;
           }
         }
         
         if(isGood){
           
           strPointer++;
           
           inString = inString.substring(strPointer);
           char cArray[inString.length() + 1];
           inString.toCharArray(cArray, sizeof(cArray));
           cmdVal = atof(cArray);
           
           if(currentPos > 0){
             currentPos = posAbsolute(mmToSteps(cmdVal), currentPos);
           } else {
             Serial.println(errorMsg);
           }
           
         } else {
           Serial.println(errorMsg);
         }
         
       } else if(cmd == "MO"){
         //return to home position
         currentPos = returnHome();
       } else if(cmd == "ST"){
         //stop
         for(int i = 0; i < 4; i++){
           digitalWrite(motorPin[i], LOW);
         }
       } else if(cmd == "ABS?"){
         //querry position
         Serial.println(stepsToMm(currentPos));
       } else {
         Serial.println(errorMsg);
       }        
     }
     
   } else { //if first char is NOT a number
   
     Serial.println(errorMsg);
     
   }
     

//    Serial.print("peek foot ");
//    Serial.println(Serial.peek());
   Serial.read(); //remove \r from buffer
   Serial.read(); //remove \n from buffer
 }
 //reset all values in preparation for next input
 strPointer = 0;
 inString = "";
 head = 0;
 cmd = "";
}

static int returnHome(){
 while(digitalRead(homeSwitch) == LOW){
   stepper.step(1);
 }
 return 1;
}

static int posAbsolute(int toPos, int curPos){
 int steps = toPos - curPos; //distance from curPos to toPos
 int stepsTaken; //pretty straight forward
 
 if(steps > 0){
   for(stepsTaken = 0; stepsTaken < steps && digitalRead(homeSwitch) == LOW; stepsTaken++){
     stepper.step(1);
//      Serial.println(stepsTaken, DEC);
   }
 } else if(steps < 0){
   for(stepsTaken = 0; stepsTaken > steps && digitalRead(homeSwitch) == LOW; stepsTaken--){
     stepper.step(-1);
//      Serial.println(stepsTaken, DEC);
   }
 }
 return curPos + stepsTaken;
}

static int mmToSteps(float mm){
 int steps = (int)(mm / mmPerStep);
 
 return steps;
}

static int stepsToMm(int steps){
 int mm = steps * mmPerStep;
 
 return mm;
}

void establishContact() {
 while (Serial.available() <= 0) {
   Serial.println("0,0,0");   // send an initial string
   delay(300);
 }
}
 
 

nickgammon

Personally I wouldn't be using the String class because that tends to leak memory. I also wouldn't use Serial.peek() - you shouldn't need that.

See this:

http://www.gammon.com.au/serial

You shouldn't need any delays at all. The methods described there let you read the data in, at whatever rate they arrive, and then process it when you are ready.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

sinkoman

After reading through the Serial page on your site, I started rewriting the entire program (for the third time :P). It's turning out far more encapsulated this time around, and i'm not encountering nearly a fraction of the problems I had the first two times. Thanks!

PaulS

Quote
After reading through the Serial page on your site, I started rewriting the entire program (for the third time smiley-razz). It's turning out far more encapsulated this time around, and i'm not encountering nearly a fraction of the problems I had the first two times.

Practice does make perfect (or, at least, better)!

Go Up