Pages: [1]   Go Down
Author Topic: GWS S125 Sail Winch Servo 360 Degrees Pan Sketch  (Read 2020 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

#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

}

Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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
« Last Edit: January 22, 2010, 11:22:13 pm by mem » Logged

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

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:
#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

Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Wales, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 37
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Wales, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 37
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 549
Posts: 46063
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Pages: [1]   Go Up
Jump to: