Serial text command to pan tilt servos

No one has sent me code, or a sketch, that works without the 5 ms delay.

I think you will find that the sketch posted in reply#1 works just fine without any delay.

If I enter P100 it doesn't work the first time. It sends a command of 0. It works with the second entry, however. But then it won't take the next command. If I type P100, enter, then P110 right after it still reads P100. It will only read a new command after the second entered line. It takes two tries to get a new position sent to the servos.

mem's example used a trailing "P" or "T".
Try "100P"

Thanks! Yes, you're right. The code works perfectly in ###C format. I don't want to appear ungrateful, but it isn't C### format. I don't think I ever said it didn't work, just not in that format. And please, I don't want to waste anyone's time! I'm VERY grateful for all the help in getting a working solution. Should the delays cause other problems I'd just switch to Mem's solutions.

If you look at what that code is doing its quite easy to add a few lines of code to changed the format to however you want. for example:

#include <Servo.h>

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

int pos = 0;                 // position
int count = 0;
char command;

Servo panServo;
Servo tiltServo;

void setup()
{
  Serial.begin(9600);
  panServo.attach(servoPanPin);  
  tiltServo.attach(servoTiltPin);  
}

void loop()
{
  if ( Serial.available())
  {
    char ch = Serial.read();

    if(ch >= '0' && ch <= '9')      {        // is ch a number?  
       pos = pos * 10 + ch - '0';           // yes, accumulate the value
         count++ ;
    }
    else {
       command = ch;
       count = 0;
       pos = 0;
    }
    if( count == 3){
      Serial.print(command); Serial.print(" "); Serial.println( pos);
      if(command == 'T')
        tiltServo.write(pos);        
      else if(command == 'P')   
         panServo.write(pos);
       pos = 0; 
       count = 0;
    } 
  }
}

Hi all, i tried to move 2 servos using the maxr´s code for the arduino board decoder wich is connected to another arduino board ...with a few changes and all i got was a lot of characters on the screen.
i´m sending S1100 to servo 1 and P2100 to servo 2, S1 and S2 are servo 1 and 2,...100 is the position .
speed is the same @4800, the Tx is connected to receiver board RX pin .
i also tried mem´s code but i couldn´t make it working .

any help would be nice, thanks

gmv

here is the modified 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 servo1Pin = 9; // Control pin for servo motor
int servo2Pin = 10; // Control pin for servo motor

void setup() {

Serial.begin(4800); // connect to the serial port
panServo.attach(servo1Pin);
tiltServo.attach(servo2Pin);

}

void loop() {

//read the serial port and create a string out of what you read

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();

if(inByte == '\n' || inByte == '\r')
break;

// Do something with the character just read...
serInString[serInIndx] = inByte;
serInIndx++;
serInString[serInIndx]= '\0';
//delay(150);
}
}

//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
}delay(500);

if((serInString[0] == 'S') && (serInString[1] == '1'))
{
//Serial.print("Pan!");

serInString[0] = ' ';
serInString[1] = ' ';
pval = atoi(serInString);

Serial.println();
//Serial.print("Value to pan servo: ");
//Serial.print(pval, DEC);

panServo.write(pval);
//delay(1);
}

if((serInString[0] == 'S') && (serInString[1] == '2'))
{
//Serial.print("Tilt!");

serInString[0] = ' ';
serInString[1] = ' ';
tval = atoi(serInString);

Serial.println();
//Serial.print("Value to tilt servo: ");
//Serial.print(tval, DEC);

tiltServo.write(tval);
// delay(1);
}
Serial.println();
// Re-init

serInIndx = 0;
icount = 0;
pval = 0;
tval = 0 ;

}

}

I haven't worked with this stuff in a while. I do know that I gave up on getting it to work with the command letter in front, like P100. So the way to do it is, for example, 1100S. But my code uses degrees and inputs and figures out those numbers. So I'd never send something like P2100, it might be 110P, for 110 degrees to Pan servo.

I can't tell from your code what is wrong, but this is my latest code and it has worked very well. (you can see the application for it at http://www.thitle.com There is a bunch of code that reads from a TPA81 Thermopile array which you can ignore. Sorry I can't be more help at the moment.

Hopefully something here will click with you. Also, I'd first try to get it working from the serial window of a PC. 9600 works fine. I'd use that. Keep in mind that you can get into timing problems with the Arduino if you deviate from norms.

#include <Servo.h>
#include <Wire.h>
#include <SoftwareSerial.h>

Servo panServo;
Servo tiltServo;

// TPA81
#define rxPin 2                                        // Pin for rx
#define txPin 3                                        // Pin for tx
#define address 0x68                                   // Address of TPA81
#define softReg 0x00                                   // Byte for software version
#define ambiant 0x01                                   // Byte for ambiant temperature
int temperature[] = {0,0,0,0,0,0,0,0};                 // Array to hold temperature data

float angle = 0; // changed to float for fractional degree rotation
boolean isFraction = false;

// *** PAN SERVO ***
// SERVO VARS 360 degrees GWServo S125 1T/2BB
//const int panMin = 1000;   // pulse width for 0 degrees
//const int panMax = 1940;  // pulse width for 360 degrees
//const int pcenter = 1000; // using 1000 for center, or 0 degrees, you may want to use something different

// SERVO VARS 180 degrees HITEC HS-311
const int panMin = 900;   // pulse width for 0 degrees
const int panMax = 2350;  // pulse width for 360 degrees
const int pcenter = 1500; // using 1000 for center, or 0 degrees, you may want to use something different

// *** TILT SERVO
const int tiltMin = 900;
const int tiltMax = 2350;

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

// Can use this later for moving servo more slowly on big jumps
//int servoPanSavePos = 0;
//int servoTiltSavePos = 0;

void setup() {
  Serial.begin(9600);         // connect to the serial port
  panServo.attach(servoPanPin, panMin, panMax);  
  tiltServo.attach(servoTiltPin, tiltMin, tiltMax);  

// Center PAN 
int pulsecenter = map(90,0,180,panMin, panMax); // 180 Servo
panServo.writeMicroseconds(pulsecenter);
// Center TILT
pulsecenter = map(45,0,180,tiltMin, tiltMax); // 180 Servo
tiltServo.writeMicroseconds(pulsecenter);
 
//INIT TPA81
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);

Wire.begin();
//delay(100);                                          // Wait to make sure everything is powerd up
  
//int software = getData(softReg);                     // Get software version 
//Serial.print("TPA81 Example  V:");
//Serial.println(software);                              // Print software version to the screen

}

void loop() {
    readSerialString();  // read, wait for command
}

void readSerialString () {
 if ( Serial.available())
  {
    char ch = Serial.read();
    
    if(ch >= '0' && ch <= '9')              // is ch a number?  
      {
      // we're in integer part of number
      if (isFraction == false)
      {
      angle = angle * 10 + ch - '0';           // yes, accumulate the value
      }
        // were in fraction, add it
        else 
        {
        angle = angle + float((ch - '0') * 0.1);
        }
    }
    else if(ch == '.')
    {
    isFraction = true; // next number will be fractional 
    }
    else if(ch == 'P'| ch == 'p')  
    {
     int pulse = mapFloat(angle,0,180,panMin, panMax); // 360
     panServo.writeMicroseconds(pulse); // 
         Serial.print("P");
         //Serial.println(angle, DEC);
        printDouble((double)angle, 1);
        angle = 0;
        isFraction = false;
    }
    else if(ch == 'T'| ch == 't')  
    {
      int pulseTilt = mapFloat(angle,0,180,tiltMin, tiltMax); 
      tiltServo.writeMicroseconds(pulseTilt); // 
//      tiltServo.write(angle); old, simple way
      Serial.print("T");
      printDouble((double)angle, 1);
//      Serial.println(angle, DEC);
      angle = 0;
      isFraction = false;
    }
    else if(ch == 'R'| ch == 'r')  
    {
      //Serial.println("Reading temp..."); 
      for(int i = 0; i < 8; i++)
        { // Loops and stores temperature data in array
        temperature[i] = getData(i+2);
        }
        // This order, sensor horizontal, positioned to left of card
        Serial.print(temperature[7]);
        Serial.print(" ");    
        Serial.print(temperature[6]);
        Serial.print(" ");    
        Serial.print(temperature[5]);
        Serial.print(" ");    
        Serial.print(temperature[4]);
        Serial.print(" ");    
        Serial.print(temperature[3]);
        Serial.print(" ");    
        Serial.print(temperature[2]);
        Serial.print(" ");    
        Serial.print(temperature[1]);
        Serial.print(" ");    
        Serial.print(temperature[0]);
        Serial.println(" ");    
    }
  }
}


int getData(int reg){                                  // Function to receive one byte of data from TPA81
  Wire.beginTransmission(address);                     // Begin communication with TPA81
  Wire.send(reg);                                      // Send reg to TPA81
  Wire.endTransmission();
  Wire.requestFrom(address, 1);                        // Request 1 byte
  while(Wire.available() < 1);                         // Wait for byte to arrive
  int data = Wire.receive();                           // Get byte
  return(data);                                        // return byte
}

// Need this to send servor degrees with fractions, like 10.5 degrees
// Thanks  Cees-Willem 
float mapFloat(float x, float in_min, float in_max, float out_min, float out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void printDouble( double val, byte precision){
  // prints val with number of decimal places determine by precision
  // precision is a number from 0 to 6 indicating the desired decimial places
  // example: lcdPrintDouble( 3.1415, 2); // prints 3.14 (two decimal places)

  if(val < 0.0){
    Serial.print('-');
    val = -val;
  }

  Serial.print (int(val));  //prints the int part
  if( precision > 0) {
    Serial.print("."); // print the decimal point
    unsigned long frac;
    unsigned long mult = 1;
    byte padding = precision -1;
    while(precision--)
  mult *=10;

    if(val >= 0)
 frac = (val - int(val)) * mult;
    else
 frac = (int(val)- val ) * mult;
    unsigned long frac1 = frac;
    while( frac1 /= 10 )
 padding--;
    while(  padding--)
 Serial.print("0");
    Serial.println(frac,DEC) ;
  }
}

hi maxr, thanks a lot...i´ll give it a try and let you know then ! :slight_smile:

gmv