Go Down

Topic: GWS S125 Sail Winch Servo 360 Degrees Pan Sketch (Read 2683 times) previous topic - next topic

maxr

From http://www.acroname.com/, I bought a GWS S125 Sail Winch Servo 1T for panning.  I want to pan 360 degrees; rather, I want to set it to any degree I want.  But I couldn't find a sketch that would do that.  So I wrote my own.  I found I had to add 24 milliseconds to get 90, 180 and 270 degrees correctly.  Hopefully, the Arduino Gods will have a fix, or other improvements.

To use this sketch, put your servo on pin 9 and load the serial window.  Type p90 for 90 degrees, or p1 for 1 degree, or p275 for 275 degrees.  You get the idea.

Code: [Select]


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

Servo panServo;

// SERIAL PORT VARS
char cString[50];  // array that will hold command string
int iBufferIndex = 0; // index of buffer characters rec'd
int iBuffer = 0;

// SERVO VARS
int icount = 0;
long pval = 0; // pan val to send to servo
float pvalfloat = 0;
int pcenter = 1000; // using 1000 for center, or 0 degrees, you may want to use something different
float degrees360inms = 940; // 360 Degrees in servo milliseconds. Again you might find something different
float degreeinms = (degrees360inms/(float)360); // 1 Degree in Milliseconds.
float msadjust = 24; // millisecond (NOT degrees) adjustment, added to above.  Kludgey, which I knew a better solution

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

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

// Default center, or close to it
panServo.writeMicroseconds(pcenter);      // close to center GWS125-IT/2BB/F ?
}

void loop() {
   readSerialString();  // read, wait for command
   processSerialString(); // process command, either pan or tilt
}

void readSerialString () {
    while (Serial.available ())
    {
    iBuffer = Serial.read();

    cString[iBufferIndex]  = iBuffer;
    iBufferIndex++;
    cString[iBufferIndex]= '\0';
    delay(10);  //never learned why this is necessary, but won't work without it
    }
   
}

void processSerialString() {
  if( iBufferIndex > 0) {
 
     // PAN
     if(cString[0] == 'P' | cString[0] == 'p') // first char should be P or T
     {
       cString[0] = ' ';
       pval = atoi(cString); // pan value is number after P, in degrees
       pvalfloat = (float)pval; // we neet float because degrees to milliseconds calc produces fractions

       if(pvalfloat==0) // we're at center so don't throw off with adjustment
       {
       pvalfloat = (pvalfloat * degreeinms); // degrees times 940/360
       }
       else
       {
       pvalfloat = (pvalfloat * degreeinms) + msadjust; // 940 milliseconds * (940 ms / 360) + ms adjustment, like 24
       }
       
       pvalfloat = pvalfloat + pcenter; // now add those degress in milliseconds to center 1000
 
     //   Serial.println();
        Serial.print("P in degrees: ");
        Serial.print(pval, DEC);
        Serial.print(" P in milliseconds: ");
        Serial.println(pvalfloat, DEC);

//      panServo.write(pval);      
     panServo.writeMicroseconds(pvalfloat);
     }
 
     
     // Re-init buffer stuff
     iBufferIndex = 0;
     iBuffer = 0;
     icount = 0;
     pval = 0;
     pvalfloat = 0;
     
  } // if string isn't 0

}


mem

#1
Jan 23, 2010, 05:21 am Last Edit: Jan 23, 2010, 05:22 am by mem Reason: 1
The reason you need to the delay in your serial routine is because you are not detecting when all the digits for the angle have been entered. This code will not be reliable if someone uses serial input that does not send all the characters at once.

You can solve the problem by using a fixed number of digits and waiting to all the digits are available, but it is awkward to have to type P000 to get 0 degrees.  Better to detect the end of the message but unfortunately the Arduino serial monitor does not send  carriage returns so you would need to type in a character to indicate the end of the message.  A convenient solution is to put the P character at the end. So 0P sets 0 degrees, 360P sets 360. Here is  an example of some code to do this.
Code: [Select]
#include <Servo.h>

Servo panServo;

int servoPanPin = 9;     // Control pin for servo motor
const int pulse0Degrees = 800;   // pulse width for 0 degrees
const int pulse360Degrees = 2200;  // pulse width for 360 degrees
const int pcenter = 1000; // using 1000 for center, or 0 degrees, you may want to use something different

int angle = 0;

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

 // Default center, or close to it
 panServo.writeMicroseconds(pcenter);      // close to center GWS125-IT/2BB/F ?
}

void loop()
{
 if ( Serial.available())
 {
   char ch = Serial.read();
   if(ch >= '0' && ch <= '9')              // is ch a number?  
     angle = angle * 10 + ch - '0';           // yes, accumulate the value
   else if(ch == 'P'| ch == 'p')  
   {
     int pulse = map(angle,0,360,pulse0Degrees, pulse360Degrees);
     panServo.writeMicroseconds(pulse);
     angle = 0;
   }
 }
}

You need to initialize  pulse0Degrees and  pulse360Degrees to the correct values for your servoe,  note the pulse widths you print in your current sketch when setting 0 degrees and 360 degrees and change the code to  initialize the variables  to those values

maxr

Thanks Mem!  I know I'm being difficult on the serial port requirement (P in front), but for those who don't have that I've integrated your code below.  Serial stuff aside, your handling of servo angles is superior, of course.  Thanks again!

Hopefully this will help anyone using Arduino to do camera/video panning.  Someday I hope to integrate it into CHDK for Canon cameras.  For those of you reading this post with similar interests, this servo is easy to use and can be plugged straight into an Arduino board, as the photo shows.  

The servo comes with a winch attachment, not standard servo wheels (one of which is attached in photo).  So if you get this servo make sure you also have/get servo wheels to attach your platform.

Code: [Select]

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

Servo panServo;

// SERVO VARS
int angle = 0;
const int pulse0Degrees = 1000;   // pulse width for 0 degrees
const int pulse360Degrees = 1940;  // pulse width for 360 degrees
const int pcenter = 1000; // using 1000 for center, or 0 degrees, you may want to use something different

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

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

// Default center, or close to it
panServo.writeMicroseconds(pcenter);      // close to center GWS125-IT/2BB/F ?
}

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?  
     angle = angle * 10 + ch - '0';           // yes, accumulate the value
   else if(ch == 'P'| ch == 'p')  
   {
     int pulse = map(angle,0,360,pulse0Degrees, pulse360Degrees);
     panServo.writeMicroseconds(pulse);
     angle = 0;
   }
 }
}



Servo attached to Arduino Nano


mem

looks good.

BTW, you can put the P in front, but you need something else as in the back to indicate the end of the message (if you don't use a fixed number of digits). It's not good practice to rely on a delay to solve this - on many systems the serial port is a low priority and there is no guarantee how quickly characters will actually be sent.

Phil Walker

Is it possible to combine this with the Firmata Sketch? as I want to controll the servo using VB and FirmataVB seems to be the easiest method. Im quite new to this so any help would be greatly appriciated.

To sumerise I want to use all of the features of Firmata aswell as this. Thanks.

Phil Walker

Would anyone be able to provide an answer or any help at all please?

Ive read through the entire sketch hat is shown above and understand it fully. However im not sure if you can easily write data to the serial port in VB (EG how you do in the serial monitor of the arduino program).

All im really after is a little guidance of how to control this 360 degree servo with the firmata sketch so I can control its postition via usb whilst maintaining all of the other Firmata controll.

Thanks very much for any help.

Cheers, Phil.

PaulS

Quote
However im not sure if you can easily write data to the serial port in VB (EG how you do in the serial monitor of the arduino program).

You can. A little reading of the VB documentation about serial communication will provide all the details.

Go Up