Show Posts
Pages: 1 2 [3]
31  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: Serial text command to pan tilt servos on: December 22, 2009, 10:21:29 am
Unfortunately, both present another problem.  printSerialString() never seems to run.  I type into the serial port and nothing is returned.  In the first example, when I had it output characters they were all boxes.

Code:
#include <Servo.h>
Servo panServo;
Servo tiltServo;

// SERIAL PORT VARS

int  serIn;             // var that will hold the bytes-in read from the serialBuffer
char serInString[80];  // array that will hold command string (though we'll only need length 3)
int serInIndx = 0;

// SERVO VARS

int icount = 0;
long pval = 0;
long tval = 0;

int servoPanPin = 9;     // Control pin for servo motor
int servoTiltPin = 10;     // Control pin for servo motor

void setup() {
 
  Serial.begin(9600);         // connect to the serial port

  panServo.attach(servoPanPin);  
  tiltServo.attach(servoTiltPin);  
  
  Serial.println("servos_ready");
}

void loop() {
  readSerialString();  
  printSerialString();
}

void readSerialString () {
  while(1) {
     if(Serial.available())
     {    
       byte inByte = Serial.read();
       if(inByte == '\n' || inByte == '\r')
          return;
  
       // Do something with the character just read...
       serInString[serInIndx]  = inByte;
       serInIndx++;
       serInString[serInIndx]= '\0';
    }
  }
}


 
//print the string all in one time
//this func as well uses global variables
void printSerialString() {
   if( serInIndx > 0) {
     int serOutIndx;
      Serial.print("Command: ");    
      //loop through all bytes in the array and print them out
      for(serOutIndx=0; serOutIndx < serInIndx; serOutIndx++) {
          Serial.print( serInString[serOutIndx] );    //print out the byte at the specified index
      }
      
    
      if(serInString[0] == 'P') // first char should be P or T
      {
      Serial.print("Pan!");
  
        serInString[0] = ' ';
        pval = atoi(serInString);
  
      Serial.println();
      Serial.print("Value to pan servo: ");
      Serial.print(pval, DEC);
      

      panServo.write(pval);      

      }
  
      if(serInString[0] == 'T')
      {
      Serial.print("Tilt!");
  
      serInString[0] = ' ';
      tval = atoi(serInString);
  
  
      Serial.println();
      Serial.print("Value to tilt servo: ");
      Serial.print(tval, DEC);
      
      tiltServo.write(tval);      
      
      }      
      
      Serial.println();
      // Re-init
      serInIndx = 0;
      icount = 0;
      pval = 0;
      tval = 0 ;
      
      
   }
 
}



32  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: Serial text command to pan tilt servos on: December 22, 2009, 09:15:05 am
I'm now wondering if the way I'm integrating the servo library is creating the problem.  

o. When the servos are called the pval and tvals remain 0.
o. When I comment out the servo calls pval and tval  get the right values.

If I put a delay in the serial.read pval and tval get the right values and the servos position properly.  I tried putting delays before after the servo calls but that didn't work either.  

Code:

#include <Servo.h>
Servo panServo;
Servo tiltServo;

// SERIAL PORT VARS

int  serIn;             // var that will hold the bytes-in read from the serialBuffer
char serInString[80];  // array that will hold command string (though we'll only need length 3)
int serInIndx = 0;

// SERVO VARS

int icount = 0;
long pval = 0;
long tval = 0;

int servoPanPin = 9;     // Control pin for servo motor
int servoTiltPin = 10;     // Control pin for servo motor

void setup() {
 
  Serial.begin(9600);         // connect to the serial port

  panServo.attach(servoPanPin);  
  tiltServo.attach(servoTiltPin);  
  
  Serial.println("servos_ready");
}

void loop() {

  //read the serial port and create a string out of what you read
  //readSerialString(serInString, serInIndx);
  readSerialString();
  
  //try to print out collected information. it will do it only if there actually is some info.
  printSerialString();

}

void readSerialString () {

  while(Serial.available() > 0)
  {
    byte inByte = Serial.read();
   delay(500);
    if(inByte == '\n' || inByte == '\r')
          break;
  
    // Do something with the character just read...
    serInString[serInIndx]  = inByte;
    serInIndx++;
    serInString[serInIndx]= '\0';
  }
}


 
//print the string all in one time
//this func as well uses global variables
void printSerialString() {
   if( serInIndx > 0) {
     int serOutIndx;
      Serial.print("Command: ");    
      //loop through all bytes in the array and print them out
      for(serOutIndx=0; serOutIndx < serInIndx; serOutIndx++) {
          Serial.print( serInString[serOutIndx] );    //print out the byte at the specified index
      }
      
    
      if(serInString[0] == 'P') // first char should be P or T
      {
      Serial.print("Pan!");
  
        serInString[0] = ' ';
        pval = atoi(serInString);
  
      Serial.println();
      Serial.print("Value to pan servo: ");
      Serial.print(pval, DEC);
      

      panServo.write(pval);      

      }
  
      if(serInString[0] == 'T')
      {
      Serial.print("Tilt!");
  
      serInString[0] = ' ';
      tval = atoi(serInString);
  
  
      Serial.println();
      Serial.print("Value to tilt servo: ");
      Serial.print(tval, DEC);
      
      tiltServo.write(tval);      
      
      }      
      
      Serial.println();
      // Re-init
      serInIndx = 0;
      icount = 0;
      pval = 0;
      tval = 0 ;
      
      
   }
 
}




33  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: Serial text command to pan tilt servos on: December 22, 2009, 07:47:32 am
THANKS!  Got the atoi function working.  So now the only thing bugging me is the need for the delay in the serial reading.  I changed to your coding but still needed to insert a delay(500) after each read or it sends strange values to the servos.
34  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: Serial text command to pan tilt servos on: December 22, 2009, 07:11:22 am
Mem, THANKS for your help.  I've put in the servo library functions as you suggested.  

But I'm still hung up on why I need delays while waiting for a string to process. .  Anyway, without a delay(500) on the Serial.read it seems the Arduino processes further instructions without waiting for the vars to be fully set.  I don't know how else to explain it.  

Is there a way to get rid of the delay?

I got the following code to work thanks to Nigel's post on the string to number.  But I still wonder if there's a more elegant way of taking any text string and converting it to a number.  Here I know I'll have 3 digits so hard coding works.

Code:

#include <Servo.h>
Servo panServo;
Servo tiltServo;

// SERIAL PORT VARS

int  serIn;             // var that will hold the bytes-in read from the serialBuffer
char serInString[80];  // array that will hold command string (though we'll only need length 3)
int serInIndx = 0;

// SERVO VARS

int icount = 0;
long pval = 0;
long tval = 0;

int servoPanPin = 9;     // Control pin for servo motor
int servoTiltPin = 10;     // Control pin for servo motor

void setup() {
 
  Serial.begin(9600);         // connect to the serial port

  panServo.attach(servoPanPin);  
  tiltServo.attach(servoTiltPin);  
  
  Serial.println("servos_ready");
}

void loop() {

  //read the serial port and create a string out of what you read
  //readSerialString(serInString, serInIndx);
  readSerialString();
  
  //try to print out collected information. it will do it only if there actually is some info.
  printSerialString();

}

void readSerialString () {
    int sb = 0;  
    if(Serial.available()) {
       // Do while we don't have a line feed or carriage return
       while (Serial.available()){
          sb = Serial.read();    
         delay(500);  // why must I have this or pval and tval don't update properly?      
          
          if(sb == 10) // line feed
          {
            break;
          }
          
          serInString[serInIndx] = sb;
          serInIndx++;
       }
    }  
}
 
//print the string all in one time
//this func as well uses global variables
void printSerialString() {
   if( serInIndx > 0) {
     int serOutIndx;
      Serial.print("Command: ");    
      //loop through all bytes in the array and print them out
      for(serOutIndx=0; serOutIndx < serInIndx; serOutIndx++) {
          Serial.print( serInString[serOutIndx] );    //print out the byte at the specified index
      }

      if(serInString[0] == 'P') // first char should be P or T
      {
      Serial.print("Pan!");
  
        // Nigel Method
        pval += (serInString[1]-48)*100;
        pval += (serInString[2]-48)*10;
        pval += (serInString[3]-48)*1;
  
      Serial.println();
      Serial.print("Value to pan servo: ");
      Serial.print(pval, DEC);
      
      panServo.write(pval);      

      }
  
      if(serInString[0] == 'T')
      {
      Serial.print("Tilt!");
  
      tval += (serInString[1]-48)*100;
      tval += (serInString[2]-48)*10;
      tval += (serInString[3]-48)*1;
  
      Serial.println();
      Serial.print("Value to tilt servo: ");
      Serial.print(tval, DEC);
      
      tiltServo.write(tval);      
      
      }      
      
      Serial.println();
      // Re-init
      serInIndx = 0;
      icount = 0;
      pval = 0;
      tval = 0 ;
      
      
   }
 
}





  
35  Forum 2005-2010 (read only) / Frequently-Asked Questions / Serial text command to pan tilt servos on: December 21, 2009, 10:25:35 pm
How can I get and process a text command while saving the servos orientation?

If I don't put a delay(1000) in the main loop, the printSerialString() function won't do some math I need correctly.  Instead of 1+700, it returns something like 695.  Odd.  At startup, I also get something like -4895.  These functions work fine in code without the servo code.

Some background, I want to control my servos through text commands sent through a com port.  I need to wait for a line and then parse it.  The first letter indicates (P)an or (T)ilt.  The next 3 characters are a 3-digit degrees number I want to orient the pan and tilt servos from.  For example P090, (Pan 90 degrees), or T045 (Tilt 45 degrees)

With the delay I assume that I won't be able to keep the servos refreshed with their current positions.  I need this because I want to send the absolute position and have them go there.  

So, how can I get the Arduino (Duemileuouv) to keep the servos refreshed while waiting for a text string from which to process a new command and orient the servos?

At this point I'm completely lost (and this Arduino stuff is new to me as of a few days ago)

Any other improvements to code greatly appreciated!  Hopefully the end result would be useful to others too.

Thanks!  Code below hopefullly.
Code:

// SERIAL PORT VARS

int  serIn;             // var that will hold the bytes-in read from the serialBuffer
char serInString[100];  // array that will hold the different bytes  100=100characters;
                        // -> you must state how long the array will be else it won't work.
int  serInIndx  = 0;    // index of serInString[] in which to insert the next incoming byte
int  serOutIndx = 0;    // index of the outgoing serInString[] array;

// SERVO VARS

char panval[2];
char tiltval[2];
int icount = 0;
long pval = 0;
long tval = 0;

int servoPanPin = 9;     // Control pin for servo motor
int servoTiltPin = 10;     // Control pin for servo motor

int pulsePanWidth = 0;    // Amount to pulse the servo
int pulseTiltWidth = 0;    // Amount to pulse the servo

long lastPanPulse = 0;    // the time in millisecs of the last pulse
long lastTiltPulse = 0;    // the time in millisecs of the last pulse
int refreshTime = 20;  // the time in millisecs needed in between pulses

int minPulse = 700;   // minimum pulse width

void setup() {
  pinMode(servoPanPin, OUTPUT);  // Set servo pin as an output pin
  pinMode(servoTiltPin, OUTPUT);  // Set servo pin as an output pin
 // pulsePanWidth = minPulse;      // Set the motor position to the minimum
 // pulseTiltWidth = minPulse;      // Set the motor position to the minimum
  Serial.begin(9600);         // connect to the serial port
  Serial.println("servos_ready");
}

void loop() {

  //read the serial port and create a string out of what you read
  //readSerialString(serInString, serInIndx);
  readSerialString();
  
  //try to print out collected information. it will do it only if there actually is some info.
  printSerialString();
 
//  updatePanServo();   // update pan servo position
//  updateTiltServo();   // update tilt servo position

  //delay(1000);

}

// called every loop().
// uses global variables servoPi, pulsewidth, lastPulse, & refreshTime
void updatePanServo() {
  // pulse the servo again if rhe refresh time (20 ms) have passed:
  if (millis() - lastPanPulse >= refreshTime) {
    digitalWrite(servoPanPin, HIGH);   // Turn the motor on
    delayMicroseconds(pulsePanWidth);  // Length of the pulse sets the motor position
    digitalWrite(servoPanPin, LOW);    // Turn the motor off
    lastPanPulse = millis();           // save the time of the last pulse
  }
}

// called every loop().
// uses global variables servoPi, pulsewidth, lastPulse, & refreshTime
void updateTiltServo() {
  // pulse the servo again if rhe refresh time (20 ms) have passed:
  if (millis() - lastTiltPulse >= refreshTime) {
    digitalWrite(servoPanPin, HIGH);   // Turn the motor on
    delayMicroseconds(pulseTiltWidth);  // Length of the pulse sets the motor position
    digitalWrite(servoTiltPin, LOW);    // Turn the motor off
    lastTiltPulse = millis();           // save the time of the last pulse
  }
}

//read a string from the serial and store it in an array
//this func uses globally set variable so it's not so reusable
//I need to find the right syntax to be able to pass to the function 2 parameters:
// the stringArray and (eventually) the index count
void readSerialString () {
    int sb;  
    if(Serial.available()) {
       //Serial.print("reading Serial String: ");     //optional confirmation
       while (Serial.available()){
          sb = Serial.read();            
          serInString[serInIndx] = sb;
          serInIndx++;
          //serialWrite(sb);                        //optional confirmation
       }
       //Serial.println();
    }  
}
 
//print the string all in one time
//this func as well uses global variables
void printSerialString() {
   if( serInIndx > 0) {
      Serial.print("Command: ");    
      //loop through all bytes in the array and print them out
      for(serOutIndx=0; serOutIndx < serInIndx; serOutIndx++) {
          Serial.print( serInString[serOutIndx] );    //print out the byte at the specified index
          //serInString[serOutIndx] = "";            //optional: flush out the content
      }
      
      Serial.println();

      if(serInString[0] == 'P')
      {
      Serial.print("Pan!");
  
      for(icount=0; icount<3; icount++)
      {
        panval[icount] = serInString[icount+1];
      }  
      
      pval = stringToNumber(panval, 3);
      pval = pval + 700;
      pulsePanWidth = pval;
      Serial.println();
      Serial.print("Value to pan servo: ");
      Serial.print(pval, DEC);
      pval = 0;
      icount = 0;
      
      //updatePanServo();

      }
  
      if(serInString[0] == 'T')
      {
      Serial.print("Tilt!");
    
      for(icount=0; icount<3; icount++)
      {
        tiltval[icount] = serInString[icount+1];
      }  

      tval = stringToNumber(tiltval, 3);
      tval = tval + 700;
      pulseTiltWidth = tval;
      Serial.println();
      Serial.print("Value to tilt servo: ");
      Serial.print(tval, DEC);
      tval = 0;
      icount = 0;    
    
      //updateTiltServo();
      
      }      
      
      //reset all the functions to be able to fill the string back with content
      serOutIndx = 0;
      serInIndx  = 0;
      Serial.println();
      
   }
 
}

/*
  THANKS tigoe.net for string to number functions!

  This method converts a string if ASCII numbers to a decimal number.
 There's no error checking in it, so it can return mistakes
 if you give it non-numeric ASCII.
 When I wrote this program, the standard C lib was not part of
 Arduino, so I couldn't use atoi().
 */
long stringToNumber(char thisString[], int length)
{
  int thisChar = 0;
  long value = 0;

  for (thisChar = length-1; thisChar >=0; thisChar--)
  {
    char thisByte = thisString[thisChar] - 48;
    value = value + powerOfTen(thisByte, (length-1)-thisChar);
  }
  return value;
}

/*
  This method takes a number between 0 and 9,
 and multiplies it by ten raised to a second number.
 */

long powerOfTen(char digit, int power) {
  long val = 1;
  if (power == 0) {
    return digit;
  }
  else {
    for (int i = power; i >=1 ; i--) {
      val = 10 * val;
    }
    return digit * val;
  }
}

Pages: 1 2 [3]