degrees of servo opens too far!

Hi All,

I am currently making a project where its a 4ft saw puppet with moving mouth. It is operated via a pir sensor which once triggered turns on a wave shield which then switches a servo motor to open and close the mouth to the wav file.

Now so far with help I have managed to achieve this with the code submitted below, But the only problem i know have is the mouth opens to far.
Does anyone know how i can shorten the degrees please?

Thank you

 //////////////////////////////////////////////////////////////////// libraries
    #include <FatReader.h>
    #include <SdReader.h>
    #include <avr/pgmspace.h>
    #include <WaveHC.h>
    #include <WaveUtil.h>
    ///////////////////////////////////////////////////////// constant pins, values

    #define swPin 14


    SdReader card;    // This object holds the information for the card
    FatVolume vol;    // This holds the information for the partition on the card
    FatReader root;   // This holds the information for the filesystem on the card
    FatReader f;      // This holds the information for the file we're play

    WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time

    // this handy function will return the number of bytes currently free in RAM, great for debugging!   
    int freeRam(void)
    {
       extern int  __bss_end;
       extern int  *__brkval;
       int free_memory;
       if((int)__brkval == 0) {
          free_memory = ((int)&free_memory) - ((int)&__bss_end);
       }
       else {
          free_memory = ((int)&free_memory) - ((int)__brkval);
       }
       return free_memory;
    }

    void sdErrorCheck(void)
    {
       if (!card.errorCode()) return;
       putstring("\n\rSD I/O error: ");
       Serial.print(card.errorCode(), HEX);
       putstring(", ");
       Serial.println(card.errorData(), HEX);
       while(1);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////

    int inputPin = 8;               // choose the input pin (for PIR sensor)
    int servoPin = 16;              // choose the input pin (for Servo)
    int pirState = LOW;             // we start, assuming no motion detected
    int val = 0;                    // variable for reading the pin status for motion sensor
    int minPulse     =  600;  // minimum servo position
    int maxPulse     =  700; // maximum servo position
    int turnRate     =  800;  // servo turn rate increment (larger value, faster rate)
    int refreshTime  =  10;   // time (ms) between pulses (50Hz)
    





    /** The Arduino will calculate these values for you **/
    int centerServo;         // center servo position
    int pulseWidth;          // servo pulse width
    long lastPulse   = 0;    // recorded time (ms) of the last pulse

    /////////////////////////////////////////////////////////////////////////// setup

    void setup() {

       pinMode(inputPin, INPUT);     // declare sensor as input for PIR

       // set up servo pin
       pinMode(servoPin, OUTPUT);  // Set servo pin 18 (analog 4) as an output pin
       centerServo = maxPulse - ((maxPulse - minPulse)/2);
       pulseWidth = centerServo;   // Give the servo a starting point (or it floats)

       // set up serial port
       Serial.begin(9600);


       putstring("Free RAM: ");       // This can help with debugging, running out of RAM is bad
       Serial.println(freeRam());      // if this is under 150 bytes it may spell trouble!

       // Set the output pins for the DAC control. This pins are defined in the library
       pinMode(2, OUTPUT);
       pinMode(3, OUTPUT);
       pinMode(4, OUTPUT);
       pinMode(5, OUTPUT);

       //  if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
       if (!card.init()) {         //play with 8 MHz spi (default faster!) 
          putstring_nl("Card init. failed!");  // Something went wrong, lets print out why
          sdErrorCheck();
          while(1);                            // then 'halt' - do nothing!
       }

       // enable optimize read - some cards may timeout. Disable if you're having problems
       card.partialBlockRead(true);

       // Now we will look for a FAT partition!
       uint8_t part;
       for (part = 0; part < 5; part++) {     // we have up to 5 slots to look in
          if (vol.init(card, part))
             break;                             // we found one, lets bail
       }
       if (part == 5) {                       // if we ended up not finding one  :(
          putstring_nl("No valid FAT partition!");
          sdErrorCheck();      // Something went wrong, lets print out why
          while(1);                            // then 'halt' - do nothing!
       }

       // Lets tell the user about what we found
       putstring("Using partition ");
       Serial.print(part, DEC);
       putstring(", type is FAT");
       Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?

       // Try to open the root directory
       if (!root.openRoot(vol)) {
          putstring_nl("Can't open root dir!"); // Something went wrong,
          while(1);                             // then 'halt' - do nothing!
       }

       // Whew! We got past the tough parts.
       putstring_nl("Ready!");

    }

    //////////////////////////////////////////////////////////// loop
    void loop() {

       val = digitalRead(inputPin);  // read input value

       if (val == HIGH)          // check if the input is LOW
       {
          if (pirState == LOW)
          {
             Serial.println("Motion Detected!");
             playcomplete("PUPPET~2.WAV");
             playcomplete("PUPPET~2.WAV");

             pirState = HIGH;

          }
       }

       else
       {
          if (pirState == HIGH)
              delay(50000);
          {

             Serial.println("Motion ended!");
             
             pirState = LOW;

          }
       }
    }


    // Plays a full file from beginning to end with no pause.

    void playcomplete(char *name)
    {
       char i;
       uint8_t volume;
       int v2;

       playfile(name);

       while (wave.isplaying)
       {
          volume = 0;
          v2 = 0;

          for (int i = 0; i < 80; i++)
          {
             v2 = max(v2, analogRead(1));
          }

          if (true)
          { 
             for(int pos = 0; pos < 50; pos += 1)  // goes from 0 degrees to 50 degrees
             {                                  // in steps of 1 degree
                servoPulse(servoPin, pos);                // tell servo to go to position in variable 'pos'
                delay(2);                       // wait 20 ms for pulse period
             }
             for(int pos = 30; pos>=1; pos-=1)     // goes from 50 degrees to 0 degrees
             {                               
                servoPulse(servoPin, pos);      // tell servo to go to position in variable 'pos'
                delay(3);                       // wait 20 ms for pulse period
             }
          }
       }
    }

    // generate a servo pulse - converts degrees to microseconds
    void servoPulse(int pin, int deg)
    {
       int pulseWidth = map(deg, 0, 180, 1000, 2000);

       digitalWrite(pin, HIGH);   // start the pulse
       delayMicroseconds(pulseWidth);  // pulse width
       digitalWrite(pin, LOW);    // stop the pulse
    }


    void playfile(char *name)
    {
       //////// stop any file already playing//////////////////////////
       if (wave.isplaying) {// already playing something, so stop it!
          wave.stop(); // stop it
       }
       // look in the root directory and open the file
       if (!f.open(root, name)) {
          putstring("Couldn't open file ");
          Serial.print(name);
          return;
       }
       // OK read the file and turn it into a wave object
       if (!wave.create(f)) {
          putstring_nl("Not a valid WAV");
          return;
       }

       // ok time to play! start playback
       wave.play();
    }

The second parameter of the servoPulse() function defines the angle to move the servo to. Use a smaller value and the servo will move less. Is there any reason why you are not using the servo library ?

Change 50 to a smaller number

          if (true)
          { 
             for(int pos = 0; pos < 50; pos += 1)  // goes from 0 degrees to 50 degrees
             {                                  // in steps of 1 degree
                servoPulse(servoPin, pos);                // tell servo to go to position in variable 'pos'
                delay(2);                       // wait 20 ms for pulse period
             }
             for(int pos = 30; pos>=1; pos-=1)     // goes from 50 degrees to 0 degrees
             {                               
                servoPulse(servoPin, pos);      // tell servo to go to position in variable 'pos'
                delay(3);                       // wait 20 ms for pulse period

Hi Bob thanks for the reply. firstly ive tried to change the numbers to a smaller amount but doesnt seem to make a difference and secondly i cant use the servo library as im using a wave shield which has conflicts with timer 1 as they use the same pins.

any other ideas please?

Change the second target values in the map() function in servoPulse()

Consider using the ServoTimer2 library http://sourceforge.net/projects/pgahtow/files/Arduino%20%28v1.0%29%20libaries/ServoTimer2.zip/download

its a good idea but i recieve the following errors just using the example shown here

// this sketch cycles three servos at different rates

#include <ServoTimer2.h>  // the servo library

// define the pins for the servos
#define rollPin  2
#define pitchPin 3
#define yawPin   4

ServoTimer2 servoRoll;    // declare variables for up to eight servos
ServoTimer2 servoPitch;
ServoTimer2 servoYaw;

void setup() {
  servoRoll.attach(rollPin);     // attach a pin to the servos and they will start pulsing
  servoPitch.attach(pitchPin);
  servoYaw.attach(yawPin);
}


// this function just increments a value until it reaches a maximum
int incPulse(int val, int inc){
   if( val + inc  > 2000 )
	return 1000 ;
   else
	 return val + inc;
}

void loop()
{
 int val;

   val = incPulse( servoRoll.read(), 1);
   servoRoll.write(val);

   val =  incPulse( servoPitch.read(), 2);
   servoPitch.write(val);

   val = incPulse(servoYaw.read(), 4);
   servoYaw.write(val);

   delay(10);
}

errors

C:\Users\djdc23\Documents\Arduino\libraries\libraries\ServoTimer2\ServoTimer2.cpp:5:26: error: WConstants.h: No such file or directory
C:\Users\djdc23\Documents\Arduino\libraries\libraries\ServoTimer2\ServoTimer2.cpp: In function 'void __vector_9()':
C:\Users\djdc23\Documents\Arduino\libraries\libraries\ServoTimer2\ServoTimer2.cpp:35: error: 'LOW' was not declared in this scope
C:\Users\djdc23\Documents\Arduino\libraries\libraries\ServoTimer2\ServoTimer2.cpp:35: error: 'digitalWrite' was not declared in this scope
C:\Users\djdc23\Documents\Arduino\libraries\libraries\ServoTimer2\ServoTimer2.cpp:42: error: 'HIGH' was not declared in this scope
C:\Users\djdc23\Documents\Arduino\libraries\libraries\ServoTimer2\ServoTimer2.cpp:42: error: 'digitalWrite' was not declared in this scope
C:\Users\djdc23\Documents\Arduino\libraries\libraries\ServoTimer2\ServoTimer2.cpp: In member function 'uint8_t ServoTimer2::attach(int)':
C:\Users\djdc23\Documents\Arduino\libraries\libraries\ServoTimer2\ServoTimer2.cpp:65: error: 'OUTPUT' was not declared in this scope
C:\Users\djdc23\Documents\Arduino\libraries\libraries\ServoTimer2\ServoTimer2.cpp:65: error: 'pinMode' was not declared in this scope

Did you download the library from the link I gave or elsewhere ?
The library predates the version 1 Arduino IDE and needs some changes to make it work. I am fairly sure that the link I gave is to the revised version.

I have attached the version from my PC which has been modified to work with later versions of the IDE

ServoTimer2.zip (6.13 KB)

this was one i had previous i will try your one

ive just tried thi sketch on the demo and the same error

// this sketch cycles three servos at different rates

#include <ServoTimer2.h>  // the servo library

// define the pins for the servos
#define rollPin  2
#define pitchPin 3
#define yawPin   4

ServoTimer2 servoRoll;    // declare variables for up to eight servos
ServoTimer2 servoPitch;
ServoTimer2 servoYaw;

void setup() {
  servoRoll.attach(rollPin);     // attach a pin to the servos and they will start pulsing
  servoPitch.attach(pitchPin);
  servoYaw.attach(yawPin);
}


// this function just increments a value until it reaches a maximum
int incPulse(int val, int inc){
   if( val + inc  > 2000 )
	return 1000 ;
   else
	 return val + inc;
}

void loop()
{
 int val;

   val = incPulse( servoRoll.read(), 1);
   servoRoll.write(val);

   val =  incPulse( servoPitch.read(), 2);
   servoPitch.write(val);

   val = incPulse(servoYaw.read(), 4);
   servoYaw.write(val);

   delay(10);
}

This example

//Test Sketch using ServoTimer2 library to drive a single standard servo attached to pin 5. write function takes an input of the pulsewidth (NOT ANGLE).
//Author: DM

#include <ServoTimer2.h>  // the servo library

ServoTimer2 servo;    // declare variables for up to eight servos
 
void setup() {
    servo.attach(5);
}

void loop()
{ 
      servo.write(2000);
      delay(1000);
      servo.write(0);
      delay(1000);
}

compiles OK with the copy of the library that I attached to my previous post.
It may not be necessary but I suggest that you close all instances of the IDE before installing the library.

aha figured it out! The .h and cpp were not in the libraries folder

Thanks

Thanks for your help HelliBob but i just have 1 mopre question for you please?

on your sketch here

//Author: DM

#include <ServoTimer2.h>  // the servo library

ServoTimer2 servo;    // declare variables for up to eight servos
 
void setup() {
    servo.attach(5);
}

void loop()
{ 
      servo.write(2000);
      delay(1000);
      servo.write(0);
      delay(1000);
}

could you tell me how I could make the servo repond to pulses so its in time with the sound please?

Thanks